> For the complete documentation index, see [llms.txt](https://docs.glesys.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.glesys.com/products/managed-services/managed-linux-hosting/how-tos/user-manual.md).

# User manual

***

Managed hosting is an operations service for all types of websites and applications that run on Linux. The core of the service is a Linux‑based virtual machine or dedicated server, delivered pre‑installed and ready to launch your website.

## Connecting to the server

To connect to your server and access files, make changes, read logs, or restart services—we recommend always using Secure Shell (SSH). In some cases, you may need exceptions; for example, some business systems are only compatible with FTPS.

Your login credentials are provided when you order the service.

To maintain a high level of security and so we know who has access to your server, we recommend personal SSH keys. Multiple individuals and companies can be linked to the same server.

In addition, we lock down SSH so that only whitelisted IP addresses can reach your server.

To add a new user—which often happens when setting up a new website—you need to contact our support team. The same applies when you want to remove access.

## Administrator access

In order to take overall responsibility and provide a secure, reliable operating environment, we do not grant root or administrator privileges.

The reason is that all parties should feel safe and know who has done what. We never touch a customer’s data; we neither edit, delete, nor create data in the customer’s home directory. You should always be confident that we have not made any manual changes, for example, to a `.htaccess` file.

Likewise, we need to be sure that the customer does not make changes to the applications for which we are responsible. We meticulously document everything performed at the application level on your server.

If you need to perform an update that requires administrator rights, please contact us for assistance.

## Server structure

We work with a standardized directory structure on the server to simplify documentation and troubleshooting. The directory layout looks like this:

### Home directory

The path to your user's home directory is `/home/httpd/<user>`.

### Website files

The files for your website are placed in `/home/httpd/<user>/<domain>/public_html` by default.

### Logs

Logs are saved in the directory `/home/httpd/<user>/logs`.

Both `<domain>-error.log` and `<domain>-access.log` are saved here, which you'll use for troubleshooting.

## Firewall routines

As part of the service, we set up a firewall to restrict and block unwanted traffic to and from your server. To make your server as secure as possible, we always start with a restrictive firewall configuration:

**Incoming rules**

* SSH: traffic is blocked, but we whitelist the IP addresses you provide for access
* FTP(S): traffic is allowed
* HTTP(S): traffic is allowed

**Outgoing rules**

* DNS: traffic is allowed
* NTP: traffic is allowed
* HTTP: traffic is blocked, but we whitelist the IP addresses you provide for access
* HTTPS: traffic is allowed

All other traffic is blocked by default.

If, for example, you need to reach an FTP server, just let us know and we’ll take care of it.

We recommend always using HTTPS whenever possible to connect to the server from outside.

## Backup routines

We ensure that a backup of your server is taken every day and retained for 14 days in a rotating schedule. If you need to restore a file or database, contact our support team, and they will help you retrieve the files.

Backup routines differ depending on whether you have managed hosting on a virtual machine or a dedicated server:

* If you are using a virtual machine, we automatically back up the entire virtual disk.
* If you have a dedicated server, we use Bacula, an open‑source backup service, to handle backups. We’ll agree on which directories and files are important, and back them up specifically.

## Updates

We ensure that your server is maintained and always kept up to date. According to a scheduled maintenance window, we continuously install the latest features and security patches.

### Maintenance window

Maintenance is performed once a week. By default, it takes place each Tuesday between 02:00 and 05:00 CET/CEST, and it usually results in no more than 10–20 minutes of downtime during that window. It may involve restarting the server or individual services that have been updated.

## Monitoring

A significant advantage of managed hosting is that we continuously monitor your server. If an error occurs in the applications we manage for you, an alert is sent to our operations team, which then identifies and resolves the issue.

We also check a specific search result on the website to verify that it is accessible to your visitors.

Response times are determined by the SLA you have signed up for; you can [read more about it here](https://glesys.com/services/extended-sla).

## Service descriptions

### SSH

By default, only whitelisted IP addresses in our firewall are allowed to connect to the service via SSH. This is to minimize the risk of unauthorized access.

### FTP(S)

By default, we allow access via FTP(S). The service responds to both encrypted and unencrypted traffic. You use the same user account to connect to FTP(S), and your IP addresses do not need to be whitelisted. This simplifies integration with external systems that often rely on the FTP protocol.

We also monitor the service and automatically block IP addresses that are used for intrusion attempts or other abuse.

If you want to grant an external service FTP access without giving full permissions to all your files, please contact us with the following information:

* Username.
* Home directory to which the user should be locked.
* The permissions the user should have: either read, write, or both.

### Crontab

To schedule jobs with cron, log in to your server via SSH and use the following command in the console.

To edit/create jobs:

{% code title="Command" %}

```
crontab -e
```

{% endcode %}

To list jobs:

{% code title="Command" %}

```
crontab -l
```

{% endcode %}

If you are curious about crontab, have a look at [Automate tasks in Linux using cron](/products/compute/guides-for-server-management/automate-tasks-in-linux-using-cron.md).

### Apache2

We are responsible for the Apache2 service, ensuring that the configuration needed to set up new websites is correct and that proxying to any backend is configured efficiently. Here are the proxy solutions we use for:

* PHP (php‑fpm)
* Python (uwsgi)
* Node.js (proxying to the application’s port)

You are responsible for code‑specific configuration in Apache2, such as redirects/rewrites performed in `.htaccess`.

We configure Apache2 so that each website that is deployed receives its own unique log files as described below:

* `/home/httpd/<user>/logs/<domain>-error.log`
* `/home/httpd/<user>/logs/<domain>-access.log`&#x20;

#### Creating new websites

If you need to host additional websites on the same server, we’ll help you. Contact our support team and let them know which domain is involved. By default, each new website is assigned a unique user with its own permissions to enhance security.

### PHP

Debian 10 (Buster) ships with PHP 7.3 as the default in its application repository, but we can also offer PHP 7.2 and 7.4 via an external repository. The versions we currently provide are therefore:

* PHP 7.2
* PHP 7.3
* PHP 7.4

We run PHP through **php‑fpm**. This means we execute your code as your user. In other words, PHP runs and creates or uploads files owned by your user. This spares you from having to manage permissions on upload directories that are world writable (`chmod 777`). We recommend that you do not change the default permissions we set (`chmod 755` for directories and `chmod 644` for files).

If you want to use **php‑cli**, it always points to the latest version that `/usr/bin/php` links to. We recommend using the alternative paths to the specific PHP version:

* `/usr/bin/php7.2`
* `/usr/bin/php7.3`
* `/usr/bin/php7.4`

### MariaDB

We are responsible for keeping the MariaDB service running. We also optimize the database settings (historical `my.cnf`) together with you. You receive full rights to create databases and users yourself.

We also **dump** all of your databases to files each night before the backup run. This prevents the databases from remaining open in RAM when we perform the backup.

#### Create a new database in MariaDB

Here is an example of how to create a new database and a dedicated user who has full privileges on that specific database. Replace `new_database` with the name of the database you want to create.

Log in to MariaDB using the command:

{% code title="Command" %}

```
mysql -u root -p
```

{% endcode %}

Create a new database using the command:

{% code title="Command" %}

```
CREATE DATABASE new_database;
```

{% endcode %}

{% code title="Output" %}

```
Query OK, 1 row affected (0.000 sec)
```

{% endcode %}

Create a user for the database:

{% code title="Command" %}

```
CREATE USER 'new_database'@'localhost' IDENTIFIED BY 'YOUR_PASSWORD';
```

{% endcode %}

{% code title="Output" %}

```
Query OK, 0 rows affected (0.001 sec)
```

{% endcode %}

Give permissions to the user:

{% code title="Command" %}

```
GRANT ALL PRIVILEGES ON new_database.* TO 'new_database'@'localhost';
```

{% endcode %}

{% code title="Output" %}

```
Query OK, 0 rows affected (0.000 sec)
```

{% endcode %}

Reload the permissions to ensure they are saved:

{% code title="Command" %}

```
FLUSH PRIVILEGES;
```

{% endcode %}

{% code title="Output" %}

```
Query OK, 0 rows affected (0.000 sec)
```

{% endcode %}

Quit the current session:

{% code title="Command" %}

```
quit
```

{% endcode %}

Log in to the new database using this command:

{% code title="Command" %}

```
mysql -u new_database -p new_database
```

{% endcode %}

By default, MariaDB listens only on `localhost`. In other words, neither you nor anyone else can reach the database over the Internet.

#### Import data into the database

To import data into your new database, run (replace `export.sql` with the name of your dump):

{% code title="Command" %}

```
mysql -u new_database -p new_database < export.sql
```

{% endcode %}

### Outgoing email (Postfix)

By default, we set up an SMTP server for outgoing email. This makes functions like `mail()` in PHP work out of the box. If you need to change the settings to connect to the SMTP server, use the following:

* Host: localhost
* Authentication: None (localhost is already whitelisted in the firewall)

### Elasticsearch

We can install the Elasticsearch version you need for your applications. What we need from you is the major version of Elasticsearch you want to use, e.g., 6 or 7.

We’ll then install that version and upgrade to the next patch release when it becomes available.

We are responsible for keeping Elasticsearch running and up‑to‑date. Since all integration with Elasticsearch is handled through the application, you retain full control and are responsible for the content, including indices and any configuration that isn’t stored in physical files.

To test whether Elasticsearch is functioning correctly, you can run:

{% code title="Command" %}

```
curl -X GET "localhost:9200/?pretty"
```

{% endcode %}

You should receive a response similar to this:

{% code title="Output" %}

```
{
  "name" : "managed",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "02CRRmY1QT-_9lNNFcGTdw",
  "version" : {
    "number" : "7.6.2",
    "build_flavor" : "default",
    "build_type" : "deb",
    "build_hash" : "ef48eb35cf30adf4db14086e8aabd07ef6fb113f",
    "build_date" : "2020-03-26T06:34:37.794943Z",
    "build_snapshot" : false,
    "lucene_version" : "8.4.0",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}
```

{% endcode %}

### Redis

Redis is a popular **in‑memory key‑value** database. By default, Redis listens only on localhost (not reachable over the Internet).

We use the default settings for how data is saved to disk. If you use Redis solely for caching and want the data stored in RAM instead of on disk, we can configure that for you.

Below you’ll see how to connect with the `cli` to flush the cache and view statistics.

<pre data-title="Commands and output. Commands and prompts are highlighted."><code><strong>redis-cli
</strong><strong>127.0.0.1:6379> select 1
</strong>OK
<strong>127.0.0.1:6379[1]> FLUSHDB
</strong>OK
<strong>127.0.0.1:6379[1]> select 0
</strong>OK
<strong>127.0.0.1:6379> FLUSHALL
</strong>OK
<strong>127.0.0.1:6379> INFO stats
</strong># Stats
total_connections_received:4
total_commands_processed:26
instantaneous_ops_per_sec:0
total_net_input_bytes:574
total_net_output_bytes:49465. 
</code></pre>

### Memcached

Memcached is an alternative to Redis, also an **in‑memory key‑value** database. It is set up in the same way as Redis—that is, it listens only on localhost and follows the default configuration wherever possible.

With us you would use it, for example, as follows:

<pre data-title="Commands and outputs. Commands are highlighted."><code><strong>telnet localhost 11211
</strong>Trying ::1...
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
<strong>flush_all
</strong>OK
<strong>quit
</strong>Connection closed by foreign host.
</code></pre>

### Node.js

It’s advisable to run your own unique installation of Node.js and npm in your home directory, so you aren’t dependent on the relatively old versions that come with the current operating system.

Here’s how to set up your own environment on a managed hosting server.

Start by logging in via SSH. Then we use **nvm** to install our environment:

{% code title="Command" %}

```
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash
```

{% endcode %}

This will output something like this:

{% code title="Output" %}

```
Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 13527  100 13527    0     0  69015      0 --:--:-- --:--:-- --:--:-- 69369
...
```

{% endcode %}

Then run:

{% code title="Multiple commands" %}

```
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"  # This loads nvm bash_completion
```

{% endcode %}

Now, let's activate the paths to Node.js by running:

{% code title="Multiple commands" %}

```
source $HOME/.bashrc
nvm install 12.16.1
```

{% endcode %}

This will output something like this:

{% code title="Output" %}

```
Downloading and installing node v12.16.1...
Downloading https://nodejs.org/dist/v12.16.1/node-v12.16.1-linux-x64.tar.xz...
############################################################################################################################################################################################################ 100.0%
Computing checksum with sha256sum
Checksums matched!
Now using node v12.16.1 (npm v6.13.4)
Creating default alias: default -> 12.16.1 (-> v12.16.1)
```

{% endcode %}

Let's verify that the installation:

{% code title="Command" %}

```
node -v
```

{% endcode %}

{% code title="Output" %}

```
v12.16.1
```

{% endcode %}

{% code title="Command" %}

```
npm -v
```

{% endcode %}

{% code title="Output" %}

```
6.13.4
```

{% endcode %}

Next, install the Express framework for your test app:

{% code title="Command" %}

```
npm install express
```

{% endcode %}

{% code title="Output" %}

```
...
+ express@4.17.1
added 50 packages from 37 contributors and audited 126 packages in 2.156s
found 0 vulnerabilities
```

{% endcode %}

Once that’s done, let's create a **Hello World** test app. Create a file using `nano -w app.js` and give it the following content:

{% code title="app.js" %}

```javascript
const express = require('express')
const app = express()
const port = 3000

app.get('/', (req, res) => res.send('Hello World!'))

app.listen(port, () => console.log(`Example app listening on port ${port}!`))
```

{% endcode %}

The Node.js application listens on port 3000, so if you want to verify that it starts correctly, you need to tell us to open TCP port 3000 in the firewall.

Once that’s done, you can test that the application starts properly by running:

{% code title="Command" %}

```
node app.js
```

{% endcode %}

It should respond with:

{% code title="Command" %}

```
Example app listening on port 3000!
```

{% endcode %}

To have the application start automatically—for example, after reboots—we use `systemd` and a so‑called service file.

Create a directory:

{% code title="Command" %}

```
mkdir -p ~/.config/systemd/user/
```

{% endcode %}

Create your service file in the directory using:

{% code title="Command" %}

```
nano -w ~/.config/systemd/user/node.service
```

{% endcode %}

Paste in the following content:

{% code title="\~/.config/systemd/user/node.service" %}

```
[Unit]
After=network.target
After=syslog.target

[Service]
WorkingDirectory=/home/httpd/<username>/
ExecStart=/home/httpd/<username>/.nvm/versions/node/v12.16.1/bin/node /home/httpd/<username>/app.js
Restart=always
StandardOutput=file:/home/httpd/<username>/logs/app.js-output.log
StandardError=file:/home/httpd/<username>/logs/app.js-error.log
SyslogIdentifier=username-node
Environment=NODE_ENV=production PORT=3000

[Install]
WantedBy=default.target
```

{% endcode %}

The next step is to contact our support team so we can ensure your user gets the proper permissions and can run processes even when logged out (we run: `loginctl enable‑linger username`). Once that’s done, it’s time to enable the service so it starts automatically on boot:

{% code title="Command" %}

```
systemctl --user enable node.service
```

{% endcode %}

This will output:

{% code title="Output" %}

```
Created symlink /home/httpd/eriksson/.config/systemd/user/multi-user.target.wants/node.service → /home/httpd/eriksson/.config/systemd/user/node.service.
```

{% endcode %}

Then, run these commands:

{% code title="Multiple commands" %}

```
systemctl --user start node.service
systemctl --user status node.service
```

{% endcode %}

This will output:

{% code title="Output" %}

```
● node.service
   Loaded: loaded (/home/httpd/eriksson/.config/systemd/user/node.service; enabled; vendor preset: enabled)
   Active: active (running) since Wed 2020-03-11 12:36:02 UTC; 47s ago
 Main PID: 2230 (node)
   CGroup: /user.slice/user-2000.slice/user@2000.service/node.service
           └─2230 /home/httpd/eriksson/.nvm/versions/node/v12.16.1/bin/node /home/httpd/eriksson/app.js

Mar 11 12:36:02 managed systemd[1549]: Started node.service.
Mar 11 12:36:02 managed eriksson-node[2230]: Example app listening on port 3000!
```

{% endcode %}

Finally, we create an Apache 2 virtual host that forwards all traffic to port 3000, which you have now set up.

### Python web application

We use uWSGI to run your Python application, which creates a socket that Apache 2 forwards all connections to. uWSGI has an **emperor mode** where you manage the configuration file for your application yourself and can restart it, for example, after a deployment.

We start by creating a Python Virtual Environment. The advantage is that, as a customer, you are not dependent on whatever Python modules Glesys has installed on your server. You handle everything yourself and have full freedom to install exactly what you need in your virtual environment using `pip`.

In our example, we run a Flask application:

{% code title="Multiple commands" %}

```
python3 -m venv python3-venv
source python3-venv/bin/activate
pip install flask
```

{% endcode %}

Create a simple "Hello World" Python script. You can place this project anywhere you like, but the location must later match the uWSGI configuration.

In this example, we use the directory `/home/httpd/<username>/<site>`. Navigate to that directory and create a file with:

{% code title="Command" %}

```
nano -w myproject.py
```

{% endcode %}

Paste in the following content:

{% code title="myproject.py" %}

```python
from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "<h1 style='color:blue'>Hello There!</h1>"

if __name__ == "__main__":
    app.run(host='0.0.0.0')
```

{% endcode %}

The next step is to create a WSGI startup script that will be invoked by uWSGI later.

{% code title="Command" %}

```
nano -w wsgi.py
```

{% endcode %}

Paste in the following content:

{% code title="wsgi.py" %}

```python
from myproject import app

if __name__ == "__main__":
    app.run()
```

{% endcode %}

Now we’ll look at your uWSGI configuration file.

Explanation of important paths:

* `chdir` – the path to the `wsgi.py` script.
* `home` – the path to your Python Virtual Environment from which uWSGI will load Python libraries.
* `socket` – the path to the socket that Apache 2 uses to communicate with your application.
* `logto` – the path to the log file (it generally shouldn’t be changed, but it’s good to know where it lives).

We have created a directory for you at `/home/httpd/<username>/vassels`; uWSGI scans this location for configuration files.

Create your uWSGI configuration file in that directory:

{% code title="Command" %}

```
nano -w /home/httpd/<username>/vassels/myapp.ini
```

{% endcode %}

And give the file the following content:

{% code title="/home/httpd/<username>/vassels/myapp.ini" %}

```ini
[uwsgi]
plugins=python3,logfile
# the base directory (full path)
chdir           = /home/httpd/<username>/<site>
# Django's wsgi file /home/httpd/<username>/<site>/wsgi.py
wsgi-file          = wsgi.py
# the virtualenv (full path)
home            = /home/httpd/<username>/python3-venv
callable        = app

# process-related settings
# master
master          = true
# maximum number of worker processes
processes       = 10
# the socket (use the full path to be safe
socket          = /home/httpd/<username>/uwsgi.sock
# ... with appropriate permissions - may be needed
# chmod-socket    = 664
# clear environment on exit
vacuum          = true
thunder-lock    = true
enable-threads  = true

logto = /home/httpd/<username>/logs/uwsgi.log
```

{% endcode %}

As we mentioned earlier, a benefit of emperor mode is that if you want to make a change or restart the application—for example, after a new deployment—you simply run:

{% code title="Command" %}

```
touch /home/httpd/<username>/vassels/myapp.ini
```

{% endcode %}

uWSGI detects that the file has been modified and automatically triggers a restart.

### Varnish

Several of our customers use Varnish. Varnish acts as a reverse proxy and caches content between the user and the web server to speed up access to your site, especially during periods of high traffic.

For example, Magento 2 generates a ready‑made `varnish.vcl` file via its admin interface.

One reason Varnish is so powerful is that the software can be tuned to work well with any code. Alternatively, you can adapt your code to how Varnish operates, using cache headers, for instance. We, of course, support both approaches.

If you choose the first option, it places high demands on you to understand how your website is built. In that case, you are responsible for both the Varnish configuration and your codebase, because they are tightly coupled.

The Varnish configuration we install is as follows:

{% code title="Default varnish.vcl" %}

```
# Marker to tell the VCL compiler that this VCL has been adapted to the
# new 4.0 format.
vcl 4.0;

# Default backend definition. Set this to point to your content server.
backend default {
    .host = "127.0.0.1";
    .port = "8080";
}

sub vcl_recv {
    # Happens before we check if we have this in cache already.
    #
    # Typically you clean up the request here, removing cookies you don't need,
    # rewriting the request, etc.
}

sub vcl_backend_response {
    # Happens after we have read the response headers from the backend.
    #
    # Here you clean the response headers, removing silly Set-Cookie headers
    # and other mistakes your backend does.
}

sub vcl_deliver {
    # Happens when we have all the pieces we need, and are about to send the
    # response to the client.
    #
    # You can do accounting or modifying the final object here.
}
```

{% endcode %}

This is the configuration that comes with Debian, and it works fine if the website is adapted for Varnish.

The exception where we always take responsibility is the following section:

{% code title="Snippet from varnish.vcl" %}

```
backend default {
    .host = "127.0.0.1";
    .port = "8080";
}
```

{% endcode %}

This is because we configure and are responsible for the web server, so it’s natural that we also adjust this.

If you want to deviate from our standard, you can upload your own `varnish.vcl` to your server and let us know where it is located; we’ll then adapt it with the correct backend and activate it.

### SSL/TLS certificates via Let's Encrypt

We can help you obtain an SSL/TLS certificate for your website. We use Let’s Encrypt and take responsibility for monitoring the certificate and ensuring it is always renewed and valid.

In order for us to enable a Let’s Encrypt certificate, you need to point the domain you want to use to the IP address of your managed hosting server. Once that’s done, we can generate a certificate for you.

The certificate itself is free; we only charge for the administrative handling. Certificate pricing is:

* 1 certificate = 20 SEK per month
* 2–19 certificates = 10 SEK each per month
* 20–99 certificates = 5 SEK each per month


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.glesys.com/products/managed-services/managed-linux-hosting/how-tos/user-manual.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
