Skip to content

Deploying Astro Site with Traefik and Systemd

This tutorial guides you through deploying an Astro Starlight site using Docker containers, Traefik as a reverse proxy with automatic SSL, and systemd for service management. By the end, you’ll have a production-ready site with automatic SSL certificates, load balancing, and automated service management. This guide assumes you have basic Linux command line knowledge and access to a server with Debian/Ubuntu, Docker, and Docker Compose installed.

  • Server with Debian/Ubuntu
  • Docker and Docker Compose installed
  • Domain name (e.g., <example.com>)
  • Basic knowledge of Linux command line
  • Node.js 18.17 or newer

If you don’t already have an Astro project, create one using the official CLI:

Terminal window
npm create astro@latest my-site

The wizard will guide you through your options (default: Starlight, empty configuration, etc.). Once created, navigate to your project directory:

Terminal window
cd my-site
Internet → Traefik (SSL/Port 443) → Busybox httpd (Static Files)
Systemd Service Management
  • Traefik: Handles SSL certificates, routing, and load balancing
  • Busybox httpd: Lightweight web server serving static Astro files
  • Systemd: Manages service lifecycle and automatic restarts
  1. Install dependencies and build

    Terminal window
    npm install
    npm run build
  2. Verify build output

    Terminal window
    ls -la dist/

    You should see your static site files in the dist/ directory.

  1. Create deployment directory

    Terminal window
    sudo mkdir -p /etc/docker-compose/<your_site>
  2. Copy build files

    Terminal window
    sudo cp -r dist /etc/docker-compose/<your_site>/
  3. Create Docker files Create the following files in /etc/docker-compose/<your_site>/:

services:
traefik:
image: traefik:latest
command:
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.web.http.redirections.entrypoint.to=websecure"
- "--entrypoints.web.http.redirections.entrypoint.scheme=https"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.letsencrypt.acme.httpchallenge=true"
- "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
- "--certificatesresolvers.letsencrypt.acme.email=<your_email>"
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
ports:
- "80:80"
- "443:443"
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- letsencrypt:/letsencrypt
networks:
- web
restart: unless-stopped
web:
image: busybox:1.36
command: httpd -f -p 80 -h /www
volumes:
- /etc/docker-compose/<your_site>/dist:/www:ro
labels:
- "traefik.enable=true"
- "traefik.http.routers.<your_site>.rule=Host(`<example.com>`)"
- "traefik.http.routers.<your_site>.entrypoints=websecure"
- "traefik.http.routers.<your_site>.tls.certresolver=letsencrypt"
- "traefik.http.services.<your_site>.loadbalancer.server.port=80"
networks:
- web
restart: unless-stopped
volumes:
letsencrypt:
networks:
web:
driver: bridge
  1. Create systemd service template

    Terminal window
    sudo tee /etc/systemd/system/docker-compose@.service > /dev/null <<EOF
    [Unit]
    Description=docker-compose %i service
    Requires=docker.service network-online.target
    After=docker.service network-online.target
    [Service]
    WorkingDirectory=/etc/docker-compose/%i
    Type=simple
    TimeoutStartSec=15min
    Restart=always
    ExecStartPre=/usr/bin/docker compose pull --quiet
    ExecStartPre=/usr/bin/docker compose build
    ExecStart=/usr/bin/docker compose up --remove-orphans
    ExecStop=/usr/bin/docker compose down --remove-orphans
    ExecReload=/usr/bin/docker compose pull --quiet
    ExecReload=/usr/bin/docker compose build
    [Install]
    WantedBy=multi-user.target
    EOF
  2. Reload systemd

    Terminal window
    sudo systemctl daemon-reload
  1. Add A record Point your domain (<example.com>) to your server’s IP address.

  2. Verify DNS propagation

    Terminal window
    nslookup <example.com>
  1. Start the service

    Terminal window
    sudo systemctl start docker-compose@<your_site>
  2. Enable on boot

    Terminal window
    sudo systemctl enable docker-compose@<your_site>
  3. Check status

    Terminal window
    sudo systemctl status docker-compose@<your_site>
  1. Check Traefik dashboard Visit http://<your_server_ip>:8080 to see the Traefik dashboard.

  2. Test HTTPS Visit https://<example.com> - you should see your Astro site with a valid SSL certificate.

  3. Check logs

    Terminal window
    sudo journalctl -u docker-compose@<your_site> -f
  1. Build new version

    Terminal window
    npm run build
  2. Update deployment files

    Terminal window
    sudo cp -r dist/* /etc/docker-compose/<your_site>/dist/
  3. Reload service

    Terminal window
    sudo systemctl reload docker-compose@<your_site>
Terminal window
# Check Docker status
sudo systemctl status docker
# Check compose logs
sudo docker compose -f /etc/docker-compose/<your_site>/compose.yaml logs
Terminal window
# Check Traefik logs
sudo docker logs traefik
# Verify domain routing
curl -I https://<example.com>
Terminal window
# Fix permissions
sudo chown -R $USER:$USER /etc/docker-compose/<your_site>/
  • Change the default Traefik dashboard port (8080) in production
  • Use strong passwords for any exposed services
  • Keep Docker and Traefik updated
  • Monitor logs regularly

You now have a production-ready Astro site deployment with:

  • Automatic SSL certificates
  • Load balancing and routing
  • Service monitoring and auto-restart
  • Easy updates and maintenance

Next steps: