How To: Run Orcpub Docker and Traefik 2.x - Orcpub/orcpub GitHub Wiki

Using Orcpub with Docker and Traefik 2.x with LetsEncrypt against CloudFlare's DNS challenge.

This assumes you have a working docker environment with:

  • Domain is on CloudFlare
  • Traefik 2.x
  • Docker

See the documentation if you want to use other acme providers for issuing certificates automatically.

https://doc.traefik.io/traefik/https/acme/#providers

First you will have to create a couple network for the containers.

docker network create -d overlay --attachable postfix
docker network create -d overlay --attachable orcpub-network

Create your CloudFlare API key if you don't have one already

https://support.cloudflare.com/hc/en-us/articles/200167836-Managing-API-Tokens-and-Keys

Traefik 2.x compose file

Edit the file to match your environment

version: '3.3'
services:
  reverse-proxy:
    image: traefik:v2.3.4
    restart: always
    command:
      # Optional debug levels for Traefik
      #- --log.level=DEBUG
      - --log.level=INFO
      
      # http listener
      - --entrypoints.web.address=:80
      - --entryPoints.web.forwardedHeaders.insecure=true
      
      # https listener
      - --entrypoints.websecure.address=:443
      - --entryPoints.websecure.forwardedHeaders.insecure=true
      - --providers.docker.endpoint=unix:///var/run/docker.sock
      
      # If running on a docker swarm 
      #- --providers.docker.swarmMode=true
      - --providers.docker.exposedbydefault=false
      - --providers.docker.network=traefik-public
      
      # Traefik Dashboard
      - --api=false
      - --api.dashboard=true
      
      # Letsencrypt resolvers for DNS Challenge
      # https://doc.traefik.io/traefik/https/acme/#providers
      - --certificatesresolvers.letsencryptresolver.acme.email=<[email protected]>
      - --certificatesresolvers.letsencryptresolver.acme.storage=/letsencrypt/acme.json
      - --certificatesresolvers.letsencryptresolver.acme.dnschallenge.provider=cloudflare
      
      # For testing rem out for production use
      - --certificatesresolvers.letsencryptresolver.acme.caServer=https://acme-staging-v02.api.letsencrypt.org/directory
      
      # The machine your running Traefix on must be able to get to CloudFlare's DNS servers
      - --certificatesResolvers.letsencryptresolver.acme.dnsChallenge.resolvers=1.1.1.1:53,1.0.0.1:53

    ports:
      - 80:80
      - 443:443

    volumes:
      # Container gets the right time
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro

      # So that Traefik can listen to the Docker events
      - /var/run/docker.sock:/var/run/docker.sock:ro

      # Traefik volume to store certificates
      - traefik:/letsencrypt

    environment:
      # Cloud flare API keys
      # https://doc.traefik.io/traefik/https/acme/#providers
      - CF_API_EMAIL=<cloudflare api email address>
      - CF_API_KEY=<cloudflare api key>

    networks:
      - traefik-public

    deploy:
      labels:
       # Traefik console
       - traefik.enable=true
       - traefik.http.routers.traefik.rule=Host(`traefik.<example.com>`)
       - traefik.http.routers.traefik.entrypoints=websecure
       - traefik.http.routers.traefik.tls.certresolver=letsencryptresolver
       - traefik.http.routers.traefik.service=api@internal
       - traefik.http.routers.traefik.middlewares=traefik
       # Basic Auth middle ware to protect the traefik console
       # https://doc.traefik.io/traefik/middlewares/basicauth/
       # Update the change:me with a new user/password!
       - traefik.http.middlewares.traefik.basicauth.users=change:$$apr1$$QjQG6kSz$$8J14ZN42RGObAlKJynES0.
       - traefik.http.services.traefik.loadbalancer.server.port=8080
       - traefik.frontend.headers.STSSeconds=31536000
       - traefik.frontend.headers.STSIncludeSubdomains=true
       - traefik.frontend.headers.STSPreload=true
   
volumes:
  traefik:
networks:
  traefik-public:
    external: true

Orcpub docker compose file

This is a much simpler setup than the Nginx configuration - ssl is handled by Traefix and LetsEncrypt, and doesn't use Nginx at all.

version: '3.2'
services:
  orcpub:
    image: orcpub/orcpub:latest
    environment:
      PORT: 8890
      # Using the postfix container below - feel free to use gmail or another smtp relay service here and rem out the postfix container
      EMAIL_SERVER_URL: 'postfix' 
      EMAIL_ACCESS_KEY: '' # If using postfix below leave blank
      EMAIL_SECRET_KEY: '' # If using postfix below leave blank
      EMAIL_SERVER_PORT: 587
      # Email address to send from, will default to '[email protected]'
      EMAIL_FROM_ADDRESS: '[email protected]'  # If using postfix below - make sure your domain name matches.
      # Email address to send errors to
      EMAIL_ERRORS_TO: ''
      EMAIL_SSL: 'FALSE'
      EMAIL_TLS: 'FALSE'

      # Datomic connection string - Make sure the <change this> matches the DATOMIC_PASSWORD below 
      DATOMIC_URL: datomic:free://datomic:4334/orcpub?password=<change this>
      # The secret used to hash your password in the browser, 20+ characters recommended
      SIGNATURE: '<change me to something unique>'
    restart: always
    depends_on:
      - datomic
    restart: unless-stopped
      # Java Container memory, don't go higher than this
      JAVA_OPTS: "-Xms4g -Xmx4g -XX:+UseG1GC"
    deploy:
      labels:
       # If redirecting http > https in Cloudflare rem this out
       # http listener
       - traefik.enable=true
       - traefik.http.routers.orcpub.entrypoints=web
       - traefik.http.routers.orcpub.rule=Host(`<host.example.com>`)
       - traefik.http.routers.orcpub.middlewares=redirect-to-https@docker
       - traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https
       
       # https listener
       - traefik.http.routers.orcpub-ssl.entrypoints=websecure
       # Match all the web urls for Orcpub itself and send it to this container
       - traefik.http.routers.orcpub-ssl.rule=(Host(`<host.example.com>`) && ( PathPrefix(`/health`) || PathPrefix(`/css`) || PathPrefix(`/dnld`) || PathPrefix(`/image`) || PathPrefix(`/js`) || PathPrefix(`/assets`) ||PathPrefix(`/favicon.ico`) || PathPrefix(`/favicon`) || PathPrefix(`/user`) || PathPrefix(`/dnd`) || PathPrefix(`/pages`) || PathPrefix(`/5e`) || PathPrefix(`/verify`) || PathPrefix(`/verification-expired`) || PathPrefix(`/verification-successful`) || PathPrefix(`/verification-sent`) || PathPrefix(`/re-verify`) || PathPrefix(`/register`) || PathPrefix(`/login`) || PathPrefix(`/user`) || PathPrefix(`/character.pdf`) || PathPrefix(`/check-email`) || PathPrefix(`/check-username`) || PathPrefix(`/reset-password`) || PathPrefix(`/send-password-reset`) || PathPrefix(`/password-reset-sent`) || PathPrefix(`/password-reset-success`) || PathPrefix(`/password-reset-expired`) || PathPrefix(`/password-reset-used`) || PathPrefix(`/terms-of-use`) || PathPrefix(`/privacy-policy`) || PathPrefix(`/community-guidelines`) || PathPrefix(`/cookies-policy`) || PathPrefix(`/following`) ))
       - traefik.http.routers.orcpub-ssl.service=orcpub-ssl
       - traefik.http.routers.orcpub-ssl.tls=true
       - traefik.http.routers.orcpub-ssl.tls.domains[0].main=<host.example.com>
       - traefik.http.routers.orcpub-ssl.tls.certresolver=letsencryptresolver
       - traefik.http.routers.orcpub-ssl.priority=3
       - traefik.http.services.orcpub-ssl.loadbalancer.server.port=8890
       # Container health checks every 30 seconds
       - traefik.http.services.orcpub-ssl.loadBalancer.healthcheck.path=/health
       - traefik.http.services.orcpub-ssl.loadBalancer.healthcheck.port=8890
       - traefik.http.services.orcpub-ssl.loadBalancer.healthcheck.scheme=http
       - traefik.http.services.orcpub-ssl.loadBalancer.healthcheck.interval=30s
       - traefik.http.services.orcpub-ssl.loadBalancer.healthcheck.timeout=2s
      resources:
        limits:
          memory: 4G
        reservations:
          memory: 4G
    depends_on:
      - datomic
    networks:
      - traefik-public
      - orcpub-network
      - postfix

  #Datomic - database server
  datomic:
    image: akiel/datomic-free
    restart: always
    environment:
      # Datomic passwords
      ADMIN_PASSWORD: <admin password>
      # Make sure the DATOMIC_PASSWORD is the same one you used in the DATOMIC_URL above
      DATOMIC_PASSWORD: <datomic password>
      # Java memory limits  Don't change these
      XMS: -Xms4g
      XMX: -Xmx4g
      ALT_HOST: datomic
    volumes:
      # Where datomic stores it's database files
      - data:/data
      - data:/log

      # Backup directory - set this to a path on the host
      # To backup the orcpub database put this in a @hourly crontab:
      # container=$(docker ps -aqf "name=^orcpub_datomic")
      # docker exec $container /datomic/bin/datomic -Xmx4g -Xms4g backup-db datomic:free://datomic:4334/orcpub?password=<change this> file:/backups/datomic/
      - /var/backups:/backups
    networks:
      - orcpub-network
    deploy:
      resources:
        limits:
          # Set memory limits to 2x+1gb so backups can run.
          memory: 9G
        reservations:
          memory: 9G

  # Optional but nice to have 
  # Random generator container
  dndgenerator:
    image: dndgenerator:latest
    deploy:
      labels:
       - traefik.enable=true
       # If redirecting http > https in Cloudflare rem this out
       - traefik.http.routers.gen.entrypoints=web
       - traefik.http.routers.gen.rule=Host(`<host.example.com>`)
       - traefik.http.routers.gen.middlewares=redirect-to-https@docker
       - traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https
       
       - traefik.http.routers.gen-ssl.entrypoints=websecure
       # Match all the web urls for dndgenerator itself and send it to this container
       - traefik.http.routers.gen-ssl.rule=(Host(`<host.example.com>`) && PathPrefix(`/generator`))
       - traefik.http.routers.gen-ssl.service=gen-ssl
       - traefik.http.routers.gen-ssl.tls=true
       - traefik.http.routers.gen-ssl.tls.domains[0].main=<host.example.com>
       - traefik.http.routers.gen-ssl.tls.certresolver=letsencryptresolver
       - traefik.http.routers.gen-ssl.priority=2
       - traefik.http.services.gen-ssl.loadbalancer.server.port=80
    networks:
      - traefik-public

  postfix:
    # If you need to relay through gmail please see https://github.com/bokysan/docker-postfix
    hostname: "postfix"
    image: "boky/postfix"
    restart: always
    environment:
      ALLOWED_SENDER_DOMAINS: "<example.com>"
      POSTFIX_hostname: "<host.example.com>"
      POSTFIX_myhostname: "<host.example.com>"
      # Debug inbound mail
      #INBOUND_DEBUGGING: 1
    networks:
      - postfix

volumes:
  data:

networks:
  postfix:
    external:
      name: postfix
  orcpub-network:
    driver: overlay
    attachable: true
  traefik-public:
    external: true