Skip to main content

Self-Hosting Linkwarden on YunoHost (Docker Hybrid)

Linkwarden is a self-hosted collaborative bookmark manager that captures webpages as screenshots and PDFs, ensuring you never lose a link to "link rot".

This guide details how to install Linkwarden on a YunoHost server using a manual Docker Compose setup. This "hybrid" approach gives us the control of Docker with the convenience of YunoHost's reverse proxy and SSL management.

Prerequisites

  • A YunoHost server (v11 or later).
  • Docker and Docker Compose installed on the server.
  • A dedicated subdomain (e.g., links.example.com) added to your YunoHost dashboard.
  • SSH access to your server.

Phase 1: Docker Configuration

We will run Linkwarden on a custom port (8200) to avoid conflicts with other internal services.

1. Create the Directory

Organise your container files. We usually store these in ~/docker/.

mkdir -p ~/docker/linkwarden
cd ~/docker/linkwarden

2. Configure Environment Variables

Generate a random secret key for security:

openssl rand -base64 32

Create the .env file:

nano .env

Paste the following configuration (update the values accordingly):

# Domain Settings
NEXTAUTH_URL=https://links.example.com
NEXTAUTH_SECRET=paste_your_openssl_string_here

# Database Settings
# Choose a strong password for the internal database
POSTGRES_PASSWORD=my_secure_db_password
DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD}@postgres:5432/postgres

# Security: Set this to 'true' AFTER creating your admin account
NEXT_PUBLIC_DISABLE_REGISTRATION=false

3. Create the Docker Compose File

Create compose.yaml:

nano compose.yaml

Paste the following:

services:
  postgres:
    image: postgres:16-alpine
    restart: always
    env_file: .env
    volumes:
      - pgdata:/var/lib/postgresql/data

  linkwarden:
    env_file: .env
    environment:
      - DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD}@postgres:5432/postgres
    restart: always
    image: ghcr.io/linkwarden/linkwarden:latest
    ports:
      - "8200:3000" # Maps Host Port 8200 to Container Port 3000
    volumes:
      - ./data:/data/data
    depends_on:
      - postgres

volumes:
  pgdata:

4. Deployment

Start the application:

docker compose up -d


Phase 2: The "Chicken-and-Egg" SSL Certificate (Crucial Step)

This is where many installations fail. If you install the Redirect app before generating the SSL certificate, YunoHost may fail to validate the domain with Let's Encrypt because it redirects the validation bot to the SSO login page.

The Error to Watch For:

Invalid response from https://.../yunohost/admin/

The Solution: Install the certificate before configuring the reverse proxy.

  1. Ensure you have added the domain in YunoHost.
  2. Do not install the "Redirect" app yet.
  3. Reload Nginx to ensure configurations are fresh:
sudo systemctl reload nginx

  1. Force the certificate installation via the command line:
sudo yunohost domain cert-install links.example.com --no-checks

Once you see "Success! The certificate has been signed," you may proceed.


Phase 3: Reverse Proxy Setup

Now that the certificate is secure, we can map the domain to our Docker container.

  1. Log in to the YunoHost Web Admin.
  2. Navigate to Applications > Install.
  3. Search for and select "Redirect" (sometimes labelled "Local Redirect").
  4. Configure as follows:
  • Domain: links.example.com
  • URL Path: /
  • Type: Proxy to a local port
  • Port: 8200
  1. Click Install.

Phase 4: Finalisation

  1. Navigate to your new site (https://links.example.com).
  2. Create your admin account immediately.
  3. Security Step: Go back to your terminal, edit .env, and change:
NEXT_PUBLIC_DISABLE_REGISTRATION=true

  1. Apply the change:
docker compose up -d

Troubleshooting

If the container appears healthy (docker ps says "healthy") but you get a 502 Bad Gateway, ensure:

  • The port in compose.yaml (8200) matches the port in the YunoHost Redirect app.
  • The Linkwarden container has finished its database migrations (check logs with docker compose logs -f).