Logo Trilium Rocks!

Server/Web

The Trilium wiki actually has a really good section on installing a server/web instance so I'll only really be expanding on the docker installation method.

Docker Compose#

Since the wiki only goes over a simple docker run command, I figured a fully-fledged docker compose file might be useful to people.

version: "3.8"
services:
  trilium:
    image: zadam/trilium:0.60-latest
    container_name: trilium
    volumes:
      - /path/to/data:/home/node/trilium-data
    restart: unless-stopped

You should replace 0.60-latest with the version of Trilium you want to run. You should also replace /path/to/data with the location you want to store your Trilium data. Without providing a volume like this, your data will not be guaranteed to be saved. You can use your XDG_CONFIG_HOME but do keep in mind the filesizes can get pretty large in the trilium-data folder so pick your location accordingly. Lastly, change the restart directive as you see fit. Having it as unless-stopped is good if you expect it to always be running.

If you want the data saved from Trilium to be saved as your local user, you'll need to add some environment variables to the mix. Add this environment config to the same level as volumes.

environment:
	- USER_UID=1001
	- USER_GID=1001

Obviously, replace these values with your own. You can check them via id -u and id -g respectively.

 

Reverse Proxy (Traefik)#

There has been a lot of issues opened on GitHub about trying to use Trilium with SSL. My best recommendation for that is to use a reverse proxy like Traefik. This will not be an exhaustive guide on Traefik, but it should be enough to get you going with SSL and Trilium.

Docker Compose#

version: "3.8"
services:
  traefik:
    image: traefik:2.10
    container_name: traefik
 
    ports:
      - "80:80" # The HTTP port
      - "443:443" # The HTTPS port
    volumes:
	    # Lets traefik view docker labels
      - /var/run/docker.sock:/var/run/docker.sock
      
        # Static config file
      - /path/to/traefik.yml:/etc/traefik/traefik.yml
      
        # Where to store the SSL certificate
      - /path/to/acme.json:/acme.json
    networks:
      - traefik-proxy

networks:
  traefik-proxy:
    name: traefik-proxy
    external: true

Obviously once again adjust the paths as make sense on your machine. You'll notice at the bottom there is an external network defined, so let's go ahead and create that with docker network create -b bridge traefik-proxy. Creating it outside of the compose file means it will still exist regardless of whether the compose files are up or down. This can be a good thing to maintain configurations between moving things around.

Traefik Config#

But now we need to create the static configuration file we defined in the compose file.

# /path/to/traefik.yml
global:
  checkNewVersion: true # optional
  sendAnonymousUsage: false # optional

entryPoints:
  web:
    address: :80
    # This http block is optional, it forces https via redirect
    http:
      redirections:
        entryPoint:
          to: web-secure
          scheme: https
          permanent: true
  web-secure:
    address: :443

providers:
  docker:
    endpoint: unix:///var/run/docker.sock
    watch: true

certificatesResolvers:
  letsencrypt:
    acme:
      email: [email protected]
      storage: /path/to/acme.json
      httpChallenge:
        entryPoint: web

Make sure you update the paths accordingly, and take a look at the comments to customize to your preference. Also make sure the email is valid!

Update Trilium Compose#

If we now take our Trilium docker compose file from earlier and update it to work with Traefik, it might look a little something like this:

version: "3.8"
services:
  trilium:
    image: zadam/trilium:0.60-latest
    container_name: trilium
    volumes:
      - /path/to/data:/home/node/trilium-data
    restart: unless-stopped
    networks:
      - traefik-proxy
    labels:
      # Tell traefik to proxy this
      - traefik.enable=true

      # Define an SSL router
      - traefik.http.routers.trilium.entrypoints=web-secure

      # Tell Traefik to listen for yourdomain.com
      - traefik.http.routers.trilium.rule=Host(`yourdomain.com`)

      # Define letsencrypt as our SSL method
      - traefik.http.routers.trilium.tls.certresolver=letsencrypt

      # Route traffic into port 8080 of this container
      - traefik.http.services.trilium.loadbalancer.server.port=8080

networks:
  traefik-proxy:
    name: traefik-proxy
    external: true

I think the comments in the file do a good job at explaining, but I'll point out some important changes. First notice the top-level networks directive that matches the one from our Traefik file. That's important to make sure we're using the correct internal network in this compose file. Next notice the networks directive on the container itself. This maps the top-level network to this container so the traffic is proxied by Traefik. Lastly there is the labels directive which is what Traefik looks at to configure how to proxy this container. For details, refer back to the comments in the file itself.

Put It All Together#

Multiple Composes#

Multiple files may seem like overkill for this case with just two containers, but setting it up like this allows you to scale and add more to your server while all still being proxied by Traefik with SSL. And since we already have everything in separate files, this is the easiest to do. Just run docker compose up on each the Traefik and Trilium compose files. Because the network we created was created externally, it doesn't actually matter what order you start them in. Once Traefik starts up, it takes over the network and starts proxying requests.

 You should be able to see it at https://yourdomain.com without any port value or SSL issues thanks to Traefik!

Single Compose#

We can go ahead and combine both of these into one large docker-compose.yml

version: "3.8"
services:
  traefik:
    image: traefik:2.10
    container_name: traefik
 
    ports:
      - "80:80" # The HTTP port
      - "443:443" # The HTTPS port
    volumes:
	    # Lets traefik view docker labels
      - /var/run/docker.sock:/var/run/docker.sock
      
        # Static config file
      - /path/to/traefik.yml:/etc/traefik/traefik.yml
      
        # Where to store the SSL certificate
      - /path/to/acme.json:/acme.json
    networks:
      - traefik-proxy
      
      
  trilium:
    image: zadam/trilium:0.60-latest
    container_name: trilium
    volumes:
      - /path/to/data:/home/node/trilium-data
    restart: unless-stopped
    networks:
      - traefik-proxy
    labels:
      # Tell traefik to proxy this
      - traefik.enable=true

      # Define an SSL router
      - traefik.http.routers.trilium.entrypoints=web-secure

      # Tell Traefik to listen for yourdomain.com
      - traefik.http.routers.trilium.rule=Host(`yourdomain.com`)

      # Define letsencrypt as our SSL method
      - traefik.http.routers.trilium.tls.certresolver=letsencrypt

      # Route traffic into port 8080 of this container
      - traefik.http.services.trilium.loadbalancer.server.port=8080


networks:
  traefik-proxy:
    name: traefik-proxy
    external: true

Then use docker compose up to start things up. You should be able to see it at https://yourdomain.com without any port value or SSL issues thanks to Traefik!