Self-hosting applications and services has never been easier.
Here I want to outline how I deploy and manage my self-hosted services on Linode with nginx, docker-compose and CloudFlare
tldr;
- create a nginx site configuration under
/etc/nginx/site-enabled/
with the correct port mapping and domain - verify
restart: always
is set in yourdocker-compose.yml
docker-compose up
- provision SSL certificate with CloudFlare / alternative with Letsencrypt
Get a cheap VPS
There are many services that offer virtual private servers for quite cheap prices.
The providers I use are Linode and DigitalOcean (affiliate links, we both get a commission if you use these links)
Finding self-hostable services
awesome-selfhosted is THE resource to find new projects.
Some are outdated, some are discontinued, many are up to date and also “docker-friendly”.
The general idea is:
- browse through the categories
- find the service you want to self-host
- check whether a
docker-compose.yml
file is present
If the project you want to self-host doesn’t have a docker-compose.yml
file, you can try to create your own.
Alternatively, if the service doesn’t depend on other containers (e.g. persistence) you can try to spin it up directly with the docker
cli and provide the --restart=always
flag.
Docker / docker-compose
If the project contains a docker-compose.yml
you’re ready to clone it.
Just git clone
the repo and cd
into it.
Understand with the help of the port mapping in the docker-compose.yml
file, on which port the service is exposed, and especially on which network:
If you find a port mapping like this:
ports:
- 8080:8080
you might want to expose it only on the local network (because by default it exposes it on 0.0.0.0
):
ports:
- 127.0.0.1:8080:8080
If there is no explicit port mapping, you might need to understand on which port the service is exposed.
Oftentimes, you can customize the HTTP port through some env var defined in the docker-compose.yml
file.
environment:
- PORT=3000
ports:
- 127.0.0.1:3000:3000
To start your service just run docker-compose up -d
(-d
so that the service will run as a daemon, in the background)
Now it’s time to set up a reverse proxy with nginx.
nginx
First of all, install nginx on your VPS.
Now take the snippet below and change it accordingly to your needs:
You’ll need to customize
YOUR_PORT
: the HTTP port on which the service is exposed through docker, e.g.3000
YOUR_SUBDOMAIN
: define a sub-domain on which the service will be reachable, e.g.stats
YOUR_TLD
: your top-level domain, e.g.example.com
your_service
: change this to a meaningful name of your service, e.g.stats
upstream your_service {
server 127.0.0.1:YOUR_PORT max_fails=5 fail_timeout=60s;
}
server {
server_name YOUR_SUBDOMAIN.YOUR_TLD;
listen 80;
listen [::]:80;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript application/activity+json application/atom+xml;
client_max_body_size 16m;
ignore_invalid_headers off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
location / {
proxy_pass http://your_service;
}
}
Put this file under /etc/nginx/sites-available/<service>
.
Then link it with ln -s /etc/nginx/sites-available/<service> /etc/nginx/sites-enabled/<service>
Also check that everything the nginx configuration is valid with nginx -t
SSL / CloudFlare
Now I encourage you to put a SSL certificate in front of your service.
The easiest way I found is to use CloudFlare to issue a free SSL certificate for my domains.
To configure Cloudflare you’ll need to log in to your domain registrar and transfer the DNS records to CloudFlare. CloudFlare provides excellent guides to do this.
Now simply get your VPS IP address and create a new DNS record in the CloudFlare dashboard.
Create a A
record that points your subdomain to your VPS IP address.
Check that the “Proxy status” is set to “Proxied” so that CloudFlare does the SSL termination.
Examples
Recently I wrote about what services I am self-hosting, here you can find practical examples I use daily.