Repository navigation
Installation with Podman
This guide installs the shop with Podman instead of Docker and uses Caddy on the server as the HTTPS reverse proxy.
At the end you have the shop at https://shop.example.com and the admin at https://admin.example.com, with automatic
certificates from Let's Encrypt.
Podman runs here rootful (as root, via sudo): Caddy needs ports 80/443 and the updater needs the Podman socket. The shop's
docker-compose.yml is used unchanged; the Docker Compose program talks to Podman's Docker-compatible socket.
Replace example.com with your own domain throughout.
Same as in Installation (2 GB RAM, 10 GB disk, two DNS records, ports 22/80/443), plus a distribution with Podman 4.9 or newer: Ubuntu 24.04, Debian 13, Fedora 40+ or RHEL/AlmaLinux/Rocky 9.4+. Older Podman versions lack the container DNS the services use to find each other.
Set up the DNS records as described in Installation#2-dns.
Ubuntu / Debian:
sudo apt update
sudo apt install -y podman netavark aardvark-dns git curl caddy
podman --version # must be 4.9 or newerFedora / RHEL family:
sudo dnf install -y podman netavark aardvark-dns git curl caddy(If your distribution has no caddy package, use the official repository: https://caddyserver.com/docs/install.)
Podman socket, plus the usual Docker socket path pointing to it (the shop's updater expects /var/run/docker.sock):
sudo systemctl enable --now podman.socket
echo 'L+ /run/docker.sock - - - - /run/podman/podman.sock' | sudo tee /etc/tmpfiles.d/podman-docker-socket.conf
sudo systemd-tmpfiles --create /etc/tmpfiles.d/podman-docker-socket.confImage names like postgres:16-alpine come from Docker Hub:
sudo mkdir -p /etc/containers/registries.conf.d
printf 'unqualified-search-registries = ["docker.io"]\nshort-name-mode = "permissive"\n' | sudo tee /etc/containers/registries.conf.d/10-docker-io.confStart containers after a reboot (Podman has no always-running daemon that does this):
sudo systemctl enable podman-restart.serviceDocker Compose (the program only, no Docker engine):
sudo curl -fSL "https://github.com/docker/compose/releases/download/v2.29.7/docker-compose-linux-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
sudo docker-compose version # prints v2.29.7On other wiki pages, where a command says
docker compose …, usesudo docker-compose …instead.
The shop's containers find each other by name (the backend connects to db). Podman answers these names with a small DNS
server (aardvark-dns) that runs on the server itself, on the gateway of each container network (e.g. 10.89.0.1).
A firewall that denies incoming traffic (ufw default deny incoming, the usual setup) also blocks the containers from asking
it: the backend cannot find the database and restarts endlessly. Unlike Docker, Podman does not open this by itself.
ufw (Ubuntu / Debian), even if you only enable ufw later. Allow DNS, and only DNS, from Podman's networks
(podman+ matches all of them: podman0, podman1, …):
sudo ufw allow in on podman+ to any port 53 comment 'Podman container DNS'Nothing becomes reachable from the internet: podman+ are internal interfaces, not the public network card.
firewalld (Fedora / RHEL): usually nothing to do. Only if the test below fails:
sudo firewall-cmd --permanent --zone=trusted --add-source=10.89.0.0/16
sudo firewall-cmd --reloadTwo throw-away containers on a test network, like the shop uses: one must find the other by name and reach the internet (the build downloads packages).
sudo podman network create dnstest
sudo podman run -d --name dnstest-a --network dnstest docker.io/library/alpine:3.20 sleep 120
sudo podman run --rm --network dnstest docker.io/library/alpine:3.20 \
sh -c 'nslookup dnstest-a >/dev/null && echo "container DNS OK"; wget -q --spider https://github.com && echo "internet OK"'
sudo podman rm -f dnstest-a
sudo podman network rm dnstestBoth container DNS OK and internet OK must be printed.
-
container DNS OKmissing: the firewall rule above is missing (sudo ufw status | grep 53), or the network backend is notnetavark(sudo podman info --format '{{.Host.NetworkBackend}}'). -
internet OKmissing (hangs,bad address,timed out): ufw blocks container traffic to the internet. Allow it and run the test again:sudo ufw default allow routed sudo ufw reload
This only lets containers connect out; the shop's ports still listen on
127.0.0.1only.
sudo git clone https://github.com/MrJSA/RustCraft.git /opt/rustwebshop
cd /opt/rustwebshop
sudo git checkout "$(sudo git tag -l 'v*' | grep -v -- -beta | sort -V | tail -1)" # newest stable releaseWhy "rustwebshop" and not "RustCraft"? RustCraft used to be called rustwebshop. The old name stays as the folder name and as the stack name in
docker-compose.yml(name: rustwebshop), so containers, networks and volumes are calledrustwebshop-…/rustwebshop_…(e.g.rustwebshop_pgdatafor the database). That is intended: renaming the stack would make existing installations start with new, empty volumes, i.e. without their database and uploads. Do not change the name indocker-compose.yml; the updater refuses to update an installation with local code changes.
sudo cp .env.example .env
sudo chmod 600 .env
sudo nano .envSet at least:
DB_PASSWORD=<output of: openssl rand -hex 24>
SHOP_PUBLIC_URL=https://shop.example.com
ADMIN_PUBLIC_URL=https://admin.example.com
# Caddy runs on the server itself: no built-in proxy, the shop ports only listen locally
COMPOSE_PROFILES=
PUBLISH_ADDR=127.0.0.1Another website on this server already uses port 8080? Add
STOREFRONT_PORT=8090(any free port) and use127.0.0.1:8090instead of127.0.0.1:8080in the Caddyfile and the checks below.ADMIN_PORT(4000) can be changed the same way; the backend additionally listens on127.0.0.1:8081.
Podman needs two adjustments that Docker does not. Create /opt/rustwebshop/docker-compose.override.yml (it is not part of
the repository, so updates never touch it):
sudo tee /opt/rustwebshop/docker-compose.override.yml > /dev/null <<'YAML'
# Podman: classic image builds (Podman has no BuildKit) and no SELinux labels on the
# Podman socket and project folder that the updater works with
services:
updater:
environment:
DOCKER_BUILDKIT: "0"
security_opt:
- label=disable
repo-move:
security_opt:
- label=disable
YAMLcd /opt/rustwebshop
sudo DOCKER_BUILDKIT=0 docker-compose up -d --build # first build takes 5–15 minutes
sudo docker-compose ps # all services "running"/"healthy"
sudo docker-compose logs backend | grep "Initial admin" # one-time admin passwordrepo-move is a one-time helper that has already finished, so ps does not list it.
No Initial admin line? The backend may still be starting: wait 30 seconds and try again. Still nothing? Run
sudo docker-compose logs --tail 20 backend. If it says Failed to connect to PostgreSQL … pool timed out, the backend
cannot resolve db: add the firewall rule from step 3, then sudo docker-compose restart backend.
Check locally that both answer before you set up Caddy:
curl -sI http://127.0.0.1:8080 | head -1 # shop
curl -sI http://127.0.0.1:4000 | head -1 # admin (a redirect to /login is fine)Replace /etc/caddy/Caddyfile with:
shop.example.com {
encode zstd gzip
request_body {
max_size 50MB
}
reverse_proxy 127.0.0.1:8080
}
admin.example.com {
encode zstd gzip
request_body {
max_size 50MB
}
reverse_proxy 127.0.0.1:4000
}
sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl enable caddy
sudo systemctl reload caddyCaddy gets the certificates on the first request. Open https://admin.example.com, log in as admin with the initial
password and choose your own (min. 12 characters).
Optional: allow the admin only from certain IP addresses by adding this at the top of the admin.example.com block:
@outside not remote_ip 203.0.113.0/24 198.51.100.7
respond @outside 403
Ubuntu / Debian (ufw):
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 443/udp
sudo ufw enableFedora / RHEL (firewalld):
sudo firewall-cmd --permanent --add-service=http --add-service=https --add-service=http3
sudo firewall-cmd --reloadDo not open 8080, 4000 or 8081. Keep the Podman DNS rule from step 3: ufw rules are only added, never replaced, so the commands above leave it in place.
Settings → System & Updates works the same as with Docker (see Updates and Release Channels). The updater controls Podman through the socket from step 3.
If an update from the admin fails while building, update manually:
cd /opt/rustwebshop
sudo mkdir -p backups
sudo docker-compose exec -T db pg_dump -U shop_user shop_db | sudo tee backups/manual-$(date +%F).sql > /dev/null
sudo git fetch --tags && sudo git checkout "$(sudo git tag -l 'v*' | grep -v -- -beta | sort -V | tail -1)"
sudo DOCKER_BUILDKIT=0 docker-compose up -d --buildDo not use Settings → System & Updates → Domains in the admin: it is meant for the built-in proxy and would start it,
which then fights with the server's Caddy over ports 80/443. With Caddy on the server, change the domains in
/etc/caddy/Caddyfile and in SHOP_PUBLIC_URL / ADMIN_PUBLIC_URL in .env, then:
sudo systemctl reload caddy
cd /opt/rustwebshop && sudo docker-compose up -d| Problem | Check |
|---|---|
Backend restarts endlessly with Failed to connect to PostgreSQL … pool timed out, no Initial admin line |
The firewall blocks container DNS: add the rule from step 3, then sudo docker-compose restart backend
|
Services cannot reach each other (name not resolved, bad address 'db') |
First the firewall rule from step 3 (sudo ufw status | grep 53). Then sudo podman info --format '{{.Host.NetworkBackend}}' must print netavark and aardvark-dns must be installed; afterwards sudo docker-compose down && sudo docker-compose up -d
|
Build fails downloading packages (npm, cargo, apk) |
Containers cannot reach the internet: see the test in step 3 (ufw default allow routed) |
Build stops with Killed or signal: 9
|
Out of memory: add swap (see Installation#1-requirements), then start again |
address already in use on 8080 or 4000 |
Another service uses the port: set STOREFRONT_PORT / ADMIN_PORT in .env (step 5) |
502 Bad Gateway |
The shop is not running: sudo docker-compose ps, curl -sI http://127.0.0.1:8080
|
short-name ... did not resolve |
The registries file from step 3 is missing |
"Updater not reachable" or permission denied on docker.sock
|
ls -l /run/docker.sock must point to /run/podman/podman.sock; systemctl status podman.socket
|
| Build fails with a BuildKit/buildx error | Start with DOCKER_BUILDKIT=0 and keep the override file from step 5 |
| Shop gone after a reboot | sudo systemctl enable podman-restart.service |
| No certificate | DNS points to the server? Ports 80/443 open? journalctl -u caddy -e
|
Everything else: Troubleshooting.
Continue with First Steps, then switch on Backups.
Getting started
Running the shop
- Admin Overview
- Updates
- Release Channels
- Domains
- Restoring a Backup
- Own Reverse Proxy
- Troubleshooting
- Security
Help & feedback