Tutorial: Docker, Cloudflare, and SWAG (Reverse Proxy)
I have seen many questions, particularly in the Kavita Discord server, asking how to setup SWAG or a reverse proxy in general. This can be a confusing and daunting prospect. I want to try and alleviate some of the mysteries or challenges to allow anyone to self-host some of the awesome project's available.
- What is a Reverse Proxy?
- The Stack
- Installing Docker Engine and Docker Compose Plugin
- Installing SWAG
- Configuring SWAG
- Adding a container to SWAG
- Cloudflare DNS
What is a Reverse Proxy?
To explain what a reverse proxy is, let's first look at a forward proxy (or just typically called a proxy).

In a standard Internet communication, computer A would reach out directly to computer C, with the client sending requests to the origin server and the origin server responding to the client. When a forward proxy is in place, A will instead send requests to B, which will then forward the request to C. C will then send a response to B, which will forward the response back to A. (Source)
Now let's look at a reverse proxy:

Typically all requests from D would go directly to F, and F would send responses directly to D. With a reverse proxy, all requests from D will go directly to E, and E will send its requests to and receive responses from F. E will then pass along the appropriate responses to D.
This provides the opportunity for multiple benefits such as load balancing, protection from attacks, caching, and SSL encryption. (Source)
The Stack
For this tutorial we will be using the following software:
- Ubuntu 22
- Docker Engine
- Docker Compose Plugin
- SWAG
I have my own domain, therobbiedavis.com, I bought through namecheap.com, however I do not use their name servers. I use Cloudflare's nameservers. I recommend this as well, not just to be able to follow this tutorial, but for the benefits mentioned above (protection from attacks, caching, and ssl).
Installing Docker Engine and Docker Compose Plugin
SSH into your server or use terminal and copy the following. This is a pretty straightforward process:
for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done
First remove any old or conflicting versions of docker
# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
Then we setup Docker's apt repo
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
finally we install the docker engine and docker compose
Installing SWAG
Create a file named docker-compose.yml
where ever you would like. Just remember the location.
---
version: "3"
services:
swag:
image: lscr.io/linuxserver/swag
container_name: swag
cap_add:
- NET_ADMIN
environment:
- PUID=1000 #id -u
- PGID=1000 #id -g
- TZ=Europe/London #change
- URL=yourdomain.url #your domain
- SUBDOMAINS=www
- VALIDATION=dns
- DNSPLUGIN=cloudflare #optional
- PROPAGATION=20
- EMAIL=<e-mail> #optional
volumes:
- /path/to/appdata/config:/config
ports:
- 443:443
- 80:80 #optional
restart: unless-stopped
Then we'll fire up the container via docker compose -f <path/to/your/docker-compose.yml> up -d
Configuring SWAG
After the container is started, we'll watch the logs with docker logs swag -f
. After some init steps, we'll notice that the container will give an error during validation due to wrong credentials. That's because we didn't enter the correct credentials for the Cloudflare API yet. We can browse to the location /config/dns-conf
which is mapped from the host location (according to above settings) /path/to/appdata/config
and edit the correct ini file for our dns provider. For Cloudflare, we'll enter our API token. The API token can be created by going to My Profile->API Tokens and creating a token with the Edit DNS permission on the DNS zones for which you wish to request certificates. In the cloudflare.ini comment out the dns_cloudflare_email
and dns_cloudflare_api_key
values, then uncomment dns_cloudflare_api_token
and add your API token against it.
Once we enter the credentials into the ini file, we'll restart the docker container via docker restart swag
and again watch the logs. After successful validation, our webserver should be up and accessible by visiting your domain name.
Adding a container to SWAG
Now let's add a container to our docker-compose.yml
. For this example I will use Kavita. We will also need to add a subdomain for this container. Optionally you could setup a "wildcard" subdomain
version: "3"
services:
swag:
image: lscr.io/linuxserver/swag
container_name: swag
....
environment:
....
- SUBDOMAINS=www,kavita #Adding Kavita subdomain
- VALIDATION=dns
...
...
kavita:
image: jvmilazz0/kavita:latest # Using the stable branch from the official dockerhub repo.
container_name: kavita
volumes:
- /your/path/to/manga:/manga
- /your/path/to/comics:/comics
- /your/path/to/books:/books
- /your/path/to/saved/config:/kavita/config # /kavita/config must not be changed
environment:
- TZ=Your/Timezone
- DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=true
ports:
- "5000:5000"
restart: unless-stopped
SWAG comes with loads of pre-defined proxy configurations, including one for Kavita. To access it all you need to do is go where you are storing SWAG's config data (See the docker-compose.yml #Installing SWAG) and find /nginx/proxy-confs
. Inside this folder you will see kavita.subdomain.config.sample
, just rename that file and remove .sample
.
After this reload your compose with docker compose -f <path/to/your/docker-compose.yml> up -d
and visit kavita.yourdomain.com
. You may notice a Cloudflare error, this is because we didn't setup a subdomain on the Cloudflare DNS so it doesn't know where to route that request.
Cloudflare DNS
To add this DNS record you will need to login to your Cloudflare account, click on your domain that you have added (by using their nameservers), can go to DNS

- Create an
A
record. - The name will be
kavita
. - The IPv4 address will be the IP to the server hosting Kavita.
Once you add this address and it propagates through, you should be able to visit kavita.yourdomain.com
and see your Kavita instance running through your reverse proxy!