The LinuxServer.io team brings you another container release featuring:
Find us at:
SWAG - Secure Web Application Gateway (formerly known as letsencrypt, no relation to Let's Encrypt™) sets up an Nginx webserver and reverse proxy with php support and a built-in certbot client that automates free SSL server certificate generation and renewal processes (Let's Encrypt and ZeroSSL). It also contains fail2ban for intrusion prevention.
We utilise the docker manifest for multi-platform awareness. More information is available from docker here and our announcement here.
Simply pulling lscr.io/linuxserver/swag:latest
should retrieve the correct image for your arch, but you can also pull specific arch images via tags.
The architectures supported by this image are:
Architecture | Available | Tag |
---|---|---|
x86-64 | ✅ | amd64-\<version tag> |
arm64 | ✅ | arm64v8-\<version tag> |
armhf | ❌ |
URL
will be yoursubdomain.duckdns.org
and the SUBDOMAINS
can be www,ftp,cloud
with http validation, or wildcard
with dns validation. You can use our duckdns image to update your IP on duckdns.org.http
validation, port 80 on the internet side of the router should be forwarded to this container's port 80dns
validation, make sure to enter your credentials into the corresponding ini (or json for some plugins) file under /config/dns-conf
yoursubdomain.duckdns.org
, leave the SUBDOMAINS
variable empty)*.yoursubdomain.duckdns.org
, set the SUBDOMAINS
variable to wildcard
)--cap-add=NET_ADMIN
is required for fail2ban to modify iptableshttps://yourdomain.url
to access the default homepage (http access through port 80 is disabled by default, you can enable it by editing the default site config at /config/nginx/site-confs/default.conf
)./config/log/letsencrypt
to see why the renewals have been failing. It is recommended to input your e-mail in docker parameters so you receive expiration notices from Let's Encrypt in those circumstances.SWAG includes many Certbot plugins out of the box, but not all plugins can be included. If you need a plugin that is not included, the quickest way to have the plugin available is to use our Universal Package Install Docker Mod.
Set the following environment variables on your container:
DOCKER_MODS=linuxserver/mods:universal-package-install
INSTALL_PIP_PACKAGES=certbot-dns-<plugin>
Set the required credentials (usually found in the plugin documentation) in /config/dns-conf/<plugin>.ini
.
It is recommended to attempt obtaining a certificate with STAGING=true
first to make sure the plugin is working as expected.
dhparams.pem
.docker exec -it swag htpasswd -c /config/nginx/.htpasswd <username>
.htpasswd
. For the first user, use the above command, for others, use the above command without the -c
flag, as it will force deletion of the existing .htpasswd
and creation of a new one/config/nginx/site-confs/default.conf
. Feel free to modify this file, and you can add other conf files to this directory. However, if you delete the default
file, a new default will be created on container start.README.md
file under /config/nginx/proxy_confs
for instructions on how to enable them. The preset confs reside in and get imported from this repo.add_header X-Robots-Tag "noindex, nofollow, nosnippet, noarchive";
This will ask Google et al not to index and list your site. Be careful with this, as you will eventually be de-listed if you leave this line in on a site you wish to be present on search engines-v /path-to-swag-config:/swag-ssl
) and in the other containers, use the cert location /swag-ssl/keys/letsencrypt/
etc
that resides under /config
in other containers (ie. -v /path-to-swag-config/etc:/swag-ssl
) and in the other containers, use the cert location /swag-ssl/letsencrypt/live/<your.domain.url>/
(This is more secure because the first method shares the entire SWAG config folder with other containers, including the www files, whereas the second method only shares the ssl certs)cert.pem
, chain.pem
, fullchain.pem
and privkey.pem
, which are generated by Certbot and used by nginx and various other appsprivkey.pfx
, a format supported by Microsoft and commonly used by dotnet apps such as Emby Server (no password)priv-fullchain-bundle.pem
, a pem cert that bundles the private key and the fullchain, used by apps like ZNC/config/fail2ban/jail.local
.conf
files, create .local
files with the same name and edit those because .conf files get overwritten when the actions and filters are updated. .local
files will append whatever's in the .conf
files (ie. nginx-http-auth.conf
--> nginx-http-auth.local
)docker exec -it swag fail2ban-client status
docker exec -it swag fail2ban-client status <jail name>
docker exec -it swag fail2ban-client set <jail name> unbanip <IP>
linuxserver/letsencrypt
imagePlease follow the instructions on this blog post.
To help you get started creating a container from this image you can either use docker-compose or the docker cli.
---
services:
swag:
image: lscr.io/linuxserver/swag:latest
container_name: swag
cap_add:
- NET_ADMIN
environment:
- PUID=1000
- PGID=1000
- TZ=Etc/UTC
- URL=yourdomain.url
- VALIDATION=http
- SUBDOMAINS=www, #optional
- CERTPROVIDER= #optional
- DNSPLUGIN=cloudflare #optional
- PROPAGATION= #optional
- EMAIL= #optional
- ONLY_SUBDOMAINS=false #optional
- EXTRA_DOMAINS= #optional
- STAGING=false #optional
volumes:
- /path/to/swag/config:/config
ports:
- 443:443
- 80:80 #optional
restart: unless-stopped
docker run -d \
--name=swag \
--cap-add=NET_ADMIN \
-e PUID=1000 \
-e PGID=1000 \
-e TZ=Etc/UTC \
-e URL=yourdomain.url \
-e VALIDATION=http \
-e SUBDOMAINS=www, `#optional` \
-e CERTPROVIDER= `#optional` \
-e DNSPLUGIN=cloudflare `#optional` \
-e PROPAGATION= `#optional` \
-e EMAIL= `#optional` \
-e ONLY_SUBDOMAINS=false `#optional` \
-e EXTRA_DOMAINS= `#optional` \
-e STAGING=false `#optional` \
-p 443:443 \
-p 80:80 `#optional` \
-v /path/to/swag/config:/config \
--restart unless-stopped \
lscr.io/linuxserver/swag:latest
Containers are configured using parameters passed at runtime (such as those above). These parameters are separated by a colon and indicate <external>:<internal>
respectively. For example, -p 8080:80
would expose port 80
from inside the container to be accessible from the host's IP on port 8080
outside the container.
Parameter | Function |
---|---|
-p 443 |
Https port |
-p 80 |
Http port (required for http validation and http -> https redirect) |
-e PUID=1000 |
for UserID - see below for explanation |
-e PGID=1000 |
for GroupID - see below for explanation |
-e TZ=Etc/UTC |
specify a timezone to use, see this list. |
-e URL=yourdomain.url |
Top url you have control over (customdomain.com if you own it, or customsubdomain.ddnsprovider.com if dynamic dns). |
-e VALIDATION=http |
Certbot validation method to use, options are http or dns (dns method also requires DNSPLUGIN variable set). |
-e SUBDOMAINS=www, |
Subdomains you'd like the cert to cover (comma separated, no spaces) ie. www,ftp,cloud . For a wildcard cert, set this exactly to wildcard (wildcard cert is available via dns validation only) |
-e CERTPROVIDER= |
Optionally define the cert provider. Set to zerossl for ZeroSSL certs (requires existing ZeroSSL account and the e-mail address entered in EMAIL env var). Otherwise defaults to Let's Encrypt. |
-e DNSPLUGIN=cloudflare |
Required if VALIDATION is set to dns . Options are acmedns , aliyun , azure , bunny , cloudflare , cpanel , desec , digitalocean , directadmin , dnsimple , dnsmadeeasy , dnspod , do , domeneshop , dreamhost , duckdns , dynu , freedns , gandi , gehirn , glesys , godaddy , google , he , hetzner , infomaniak , inwx , ionos , linode , loopia , luadns , namecheap , netcup , njalla , nsone , ovh , porkbun , rfc2136 , route53 , sakuracloud , standalone , transip , and vultr . Also need to enter the credentials into the corresponding ini (or json for some plugins) file under /config/dns-conf . |
-e PROPAGATION= |
Optionally override (in seconds) the default propagation time for the dns plugins. |
-e EMAIL= |
Optional e-mail address used for cert expiration notifications (Required for ZeroSSL). |
-e ONLY_SUBDOMAINS=false |
If you wish to get certs only for certain subdomains, but not the main domain (main domain may be hosted on another machine and cannot be validated), set this to true |
-e EXTRA_DOMAINS= |
Additional fully qualified domain names (comma separated, no spaces) ie. extradomain.com,subdomain.anotherdomain.org,*.anotherdomain.org |
-e STAGING=false |
Set to true to retrieve certs in staging mode. Rate limits will be much higher, but the resulting cert will not pass the browser's security test. Only to be used for testing purposes. |
-v /config |
Persistent config files |
This image utilises cap_add
or sysctl
to work properly. This is not implemented properly in some versions of Portainer, thus this image may not work if deployed through Portainer.
You can set any environment variable from a file by using a special prepend FILE__
.
As an example:
-e FILE__MYVAR=/run/secrets/mysecretvariable
Will set the environment variable MYVAR
based on the contents of the /run/secrets/mysecretvariable
file.
For all of our images we provide the ability to override the default umask settings for services started within the containers using the optional -e UMASK=022
setting.
Keep in mind umask is not chmod it subtracts from permissions based on it's value it does not add. Please read up here before asking for support.
When using volumes (-v
flags), permissions issues can arise between the host OS and the container, we avoid this issue by allowing you to specify the user PUID
and group PGID
.
Ensure any volume directories on the host are owned by the same user you specify and any permissions issues will vanish like magic.
In this instance PUID=1000
and PGID=1000
, to find yours use id your_user
as below:
id your_user
Example output:
uid=1000(your_user) gid=1000(your_user) groups=1000(your_user)
We publish various Docker Mods to enable additional functionality within the containers. The list of Mods available for this image (if any) as well as universal mods that can be applied to any one of our images can be accessed via the dynamic badges above.
Shell access whilst the container is running:
docker exec -it swag /bin/bash
To monitor the logs of the container in realtime:
docker logs -f swag
Container version number:
docker inspect -f '{{ index .Config.Labels "build_version" }}' swag
Image version number:
docker inspect -f '{{ index .Config.Labels "build_version" }}' lscr.io/linuxserver/swag:latest
Most of our images are static, versioned, and require an image update and container recreation to update the app inside. With some exceptions (noted in the relevant readme.md), we do not recommend or support updating apps inside the container. Please consult the Application Setup section above to see if it is recommended for the image.
Below are the instructions for updating containers:
Update images:
All images:
docker-compose pull
Single image:
docker-compose pull swag
Update containers:
All containers:
docker-compose up -d
Single container:
docker-compose up -d swag
You can also remove the old dangling images:
docker image prune
Update the image:
docker pull lscr.io/linuxserver/swag:latest
Stop the running container:
docker stop swag
Delete the container:
docker rm swag
Recreate a new container with the same docker run parameters as instructed above (if mapped correctly to a host folder, your /config
folder and settings will be preserved)
You can also remove the old dangling images:
docker image prune
[!TIP] We recommend Diun for update notifications. Other tools that automatically update containers unattended are not recommended or supported.
If you want to make local modifications to these images for development purposes or just to customize the logic:
git clone https://github.com/linuxserver/docker-swag.git
cd docker-swag
docker build \
--no-cache \
--pull \
-t lscr.io/linuxserver/swag:latest .
The ARM variants can be built on x86_64 hardware and vice versa using lscr.io/linuxserver/qemu-static
docker run --rm --privileged lscr.io/linuxserver/qemu-static --reset
Once registered you can define the dockerfile to use with -f Dockerfile.aarch64
.
priv-fullchain-bundle.pem
.certbot-dns-dynudns
.stream.conf
inside the container to allow users to include their own block in nginx.conf
.google-domains
.STAGING=true
, and failures in revoking.ssl.conf
.SUBDOMAINS
var as optional.resolver.conf
and patch for CVE-2021-32637
.dhparams.pem
per RFC7919. Added worker_processes.conf
, which sets the number of nginx workers, and resolver.conf
, which sets the dns resolver. Both conf files are auto-generated only on first start and can be user modified later.CERTPROVIDER
env var. Update aliyun, domeneshop, inwx and transip dns plugins with the new plugin names. Hide donoteditthisfile.conf
because users were editing it despite its name. Suppress harmless error when no proxy confs are enabled.