Traefik and LetsEncrypt without Internet for Local Vaultwarden Application?

Hello community, I want to run Vaultwarden purely locally.

The "website" is accessible at vault.domain.local that's not my problem. My problem is that this password safe requires SSL or HTTPS to work.

Hence my question, how could you solve the fact that I get an SSL certificate via Traefik without putting the "application" on the Internet?

I could also use vault.domain.de if necessary, but how would it be possible to get this LetsEncrypt certificate without the Internet?

Hope you know and understand what I mean and can help me to solve this.

Hello @csaeum,

You can generate local certificates (e.g. using mkcerts) and tell Traefik to use those certs like so: Traefik TLS Documentation - Traefik

Hope it helps :smiley:

Okay thanks, but don't I have the problem of the self-created certificates and the error message then being displayed in the browser?

You can use the DNS01 Challenge to get the certificate from LE. Your Traefik instance needs internet access, but there is no need of a route from the internet to your application.

Yes, with self-signed certs you'd get annoying error messages. We get valid TLS certificates for our development environments by using the DNS01 challenge. The Traefik container that acts as reverse-proxy in front of our PHP containers isn't reachable from the internet, but it can connect to the internet.

The domain for which we're trying to get certs is hosted at Google Cloud DNS so we provided GCP service-account credentials to the Traefik container and it uses those to create a DNS-record, asks Let's Encrypt to validate it, downloads the cert and deletes the DNS-record. The process only takes a few seconds. Because it's a valid cert you don't get any errors. So the development host is never publicly reachable. You could use any other DNS-provider that Traefik supports of course. It works very well for us.

Unfortunately I can't do a DNS challenge because our domain provider doesn't allow changing the DNS entries via API.

An alternative I'm considering would be:

I make the environment from Docker and on a VServer directly to the network and block all IPs except from Germany.

In addition then an AUTH from Traefik unless it comes from our location with a fixed IP!

What do you all mean?

I reconsidered. If I only want to access the MSSQL without encryption and security but only the user and password from the MSSQL.

But still through Traefik. How easy would it have to be then?

Here are my configs:
Traefik:

version: "3.3"

volumes:
  letsencrypt-data:
    driver: local-persist
    driver_opts:
      mountpoint: ${CONTAINERVOLUMES}/letsencrypt

services:
  traefik:
    image: "traefik:v2.10"
    container_name: ${COMPOSE_PROJECT_NAME}
    command:
      - "--accesslog=true"
      - "--api=true"
      - "--api.dashboard=true"
      - "--log.filePath=/logs/traefik.log" 
      - "--log.level=DEBUG"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      # HTTP & HTTPS
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      # MSSQL
      - "--entrypoints.mssql.address=:1433"
      # VIDEO
      - "--entrypoints.video.address=:10000/udp"
      # LetsEnCryypt
      - "--certificatesresolvers.myresolver.acme.httpchallenge=true"
      - "--certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=web"
      - "--certificatesresolvers.myresolver.acme.caserver=https://acme-v02.api.letsencrypt.org/directory"
      - "--certificatesresolvers.myresolver.acme.email=${LETSENCRYPT_EMAIL}"
      - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/${COMPOSE_PROJECT_NAME}.json"
    labels:
      - traefik.enable=true
      # Routers
      - traefik.http.routers.http-catchall.entrypoints=web
      - traefik.http.routers.http-catchall.middlewares=redirect-to-https
      - traefik.http.routers.http-catchall.rule=hostregexp(`{host:.+}`)
      # HTTPS
      - traefik.http.routers.${COMPOSE_PROJECT_NAME}.rule=${HOSTRULE}
      - traefik.http.routers.${COMPOSE_PROJECT_NAME}.entrypoints=websecure
      - traefik.http.routers.${COMPOSE_PROJECT_NAME}.service=api@internal
      - traefik.http.routers.${COMPOSE_PROJECT_NAME}.tls.certresolver=myresolver
      - traefik.http.routers.${COMPOSE_PROJECT_NAME}.middlewares=${COMPOSE_PROJECT_NAME}_Auth
      - traefik.http.middlewares.${COMPOSE_PROJECT_NAME}_Auth.basicauth.removeheader=true
      # Passwort beachten - $ muss mit einen 2ten $ versehen werden
      # Password generieren: echo $(htpasswd -nb user password) | sed -e s/\\$/\\$\\$/g
      - traefik.http.middlewares.${COMPOSE_PROJECT_NAME}_Auth.basicauth.users=csaeum:$$1$$X[kMyb^l$$Npy/uslnNuMB4pK0focS00
      - traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https
      # TCP
      - traefik.tcp.routers.${COMPOSE_PROJECT_NAME}.entrypoints=mssql
      - traefik.tcp.routers.${COMPOSE_PROJECT_NAME}.service=api@internal
      - traefik.tcp.routers.${COMPOSE_PROJECT_NAME}.tls.certresolver=myresolver
    networks:
      - "${PROXY_NETWORK}"
      - "default"
    ports:
      - "80:80"
      - "443:443"
      - "1443:1443"
      - "10000:10000"
    volumes:
      - letsencrypt-data:/letsencrypt
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - ./logs/:/logs/

networks:
  traefik_proxy:
    external:
      name: ${PROXY_NETWORK}
  default:
    driver: bridge

MSSQL:

version: "3.7"

volumes:
  mssql-data:
    driver: local-persist
    driver_opts:
      mountpoint: ${CONTAINERVOLUMES}/mssql
  mssql-backup:
    driver: local-persist
    driver_opts:
      mountpoint: ${CONTAINERVOLUMES}/backup

services:
  db:
    container_name: ${COMPOSE_PROJECT_NAME}-JTL
    image: mcr.microsoft.com/mssql/server:2022-latest
    user: root
    environment:
      ACCEPT_EULA: Y
      MSSQL_SA_PASSWORD: ${MSSQL_SA_PASSWORD}
      # "Developer" or "Express" or "Standard"
      MSSQL_PID: Developer
      MSSQL_LCID: 1031
      MSSQL_COLLATION: Latin1_General_CI_AS
      TZ: ${TIMEZONE}
      MSSQL_DATA_DIR: /var/opt/mssql/data
      MSSQL_LOG_DIR: /var/opt/mssql/log
#    ports:
#      - 1433:1433
#      - 49200:1433
    volumes:
      - mssql-data:/var/opt/mssql
      - mssql-backup:/backup
    labels:
      # Enable Traefik and network
      - traefik.docker.network=${PROXY_NETWORK}
      - traefik.enable=true
      # TCP
      - traefik.tcp.routers.mssql.entrypoints=mssql
#      - traefik.tcp.routers.mssql.rule=${HOSTRULE}
      - traefik.tcp.routers.mssql.rule=HostSNI(`*`)
      - traefik.tcp.routers.mssql.service=mssql
      - traefik.tcp.routers.mssql.tls=true
      - traefik.tcp.routers.mssql.tls.certresolver=myresolver
#      - traefik.tcp.routers.mssql.tls.domains[0].main=${HOST}
      - traefik.tcp.routers.mssql.tls.passthrough=true
      - traefik.tcp.services.mssql.loadbalancer.server.port=1433

  backup:
    container_name: ${COMPOSE_PROJECT_NAME}-JTL-Backup
    image: bbtsoftwareag/mssql-backup
    # for using the cleanup feature, use the backup volume from db.
    volumes:
      - mssql-backup:/backup
    environment:
      BACKUP_AGE: 3
      BACKUP_CLEANUP: "true"
      CRON_SCHEDULE: 00 06,12,18 * * *
      DB_NAMES: eazybusiness
      DB_SERVER: db
      DB_PASSWORD: ${MSSQL_SA_PASSWORD}
      DB_USER: SA
      PACK: "zip"
      TZ: ${TIMEZONE}

    networks:
      - default

If you want a plain WhateverSQL passthrough, you need to enable a plain TCP router and TCP service in Traefik.

Do not enable any TLS on it, remove according labels, or Traefik will create a (custom) cert for it. Only use HostSNI(`*`), do not place a domain name in there.

Check this simple Traefik TCP example.

but if I want to operate multiple MSSQL instances.
Would I have to specify a domain name for SNI so that Traefik knows where to route it?

In this case you would need to use a different port.

Using HostSNI() with domain only works when TLS is used and Traefik has access to (or even created) the cert.

Hi
I'm trying to also run vaultwarden locally and have a domain hosted on cloudflare. How do i provide the account credentials to traefik to get the certs working? Do i add them to the static config under DNS challenge?

Traefik uses go-acme library for LetsEncrypt. When using dnsChallenge, credentials for DNS providers are supplied via env vars, see doc.

Thanks, DNS challenge works now