Skip to main content

Hosting on Docker

tip

The easiest way to get started with Fider is to use our Cloud Instance - no installation, no worrying about updates, setup, configuration, or maintenance. And there's a free plan, so you can get started at no cost.

💪 Find out more

Prerequisites​

Docker https://docs.docker.com/engine/install​

We don't distribute Linux or Windows binaries, so you need Docker to host Fider. Docker gives Fider the same runtime everywhere, and most cloud providers support it. You can run it on its own or with a container orchestrator.

Docker Compose https://docs.docker.com/compose/install​

This installation guide uses Docker Compose to simplify the setup of containers.

PostgreSQL 12+ Database​

Fider requires PostgreSQL 12+. For simplicity, this guide runs Postgres in a container. You can also install it on the host machine or use a separate database server.

E-mail Sender​

Fider cannot start without an email provider, because sign-in links are sent by email. Choose one of:

If you just want to try Fider out, you can use a testing SMTP server.

Installing and Running​

Step 1: Create a docker compose file​

Create a /var/fider folder and copy content below into a file /var/fider/docker-compose.yml. Read the inline comments to know what each setting is used for and modify them appropriately.

services:
db:
restart: always
image: postgres:17
volumes:
- /var/fider/pg_data:/var/lib/postgresql/data
environment:
POSTGRES_USER: fider
POSTGRES_PASSWORD: s0m3g00dp4ssw0rd
app:
restart: always
image: getfider/fider:stable
ports:
- "80:3000"
environment:
# Public URL of your Fider site, including http:// or https://
BASE_URL: http://localhost

# Connection string to the PostgreSQL database
DATABASE_URL: postgres://fider:s0m3g00dp4ssw0rd@db:5432/fider?sslmode=disable

# Generate a secure secret, for example using https://jwtsecrets.com
JWT_SECRET: VERY_STRONG_SECRET_SHOULD_BE_USED_HERE

# From which account e-mails will be sent
EMAIL_NOREPLY: noreply@yourdomain.com

###
# EMAIL
# Uncomment ONE of the groups below: Mailgun, SMTP or Amazon SES
###

# EMAIL_MAILGUN_API: key-yourkeygoeshere
# EMAIL_MAILGUN_DOMAIN: yourdomain.com
# EMAIL_MAILGUN_REGION: US

# EMAIL_SMTP_HOST: smtp.yourdomain.com
# EMAIL_SMTP_PORT: 587
# EMAIL_SMTP_USERNAME: user@yourdomain.com
# EMAIL_SMTP_PASSWORD: s0m3p4ssw0rd

# EMAIL_AWSSES_REGION: us-east-1
# EMAIL_AWSSES_ACCESS_KEY_ID: youraccesskeygoeshere
# EMAIL_AWSSES_SECRET_ACCESS_KEY: yoursecretkeygoeshere

# See "Configuration reference" below for all other settings

Pay close attention to BASE_URL. It must be the exact public URL people use to reach Fider, including http:// or https://. Fider uses it to build every link, including the sign-in links it emails.

The Docker Compose file above defines two services: db and app. If you're using an external Postgres database, remove the db service and set DATABASE_URL to your connection string.

For multiple feedback boards on one deployment, see Multi-Tenant Hosting.

Step 2: Pull the images and run them​

Open your favorite terminal, navigate to /var/fider and run

docker compose pull
docker compose up -d

Important! You may see messages like Error: dial tcp <ip-address>:5432: connect: connection refused. Don't panic. This is expected when PostgreSQL runs in Docker: Fider started before the database was ready. Docker restarts Fider, and it connects once the database is up.

You can find the logs by using docker compose logs app. The message http server started on :3000 means everything is ok and you're ready to go.

Just open your favorite browser and navigate to http://localhost. You should see a page like the following.

Docker Installation

Configuration reference​

Fider is configured entirely through environment variables, set in the environment: section of your docker-compose.yml. The tables below list every setting relevant to self-hosting.

A few general notes:

  • Booleans take true or false. Quote them in YAML (SSL_AUTO: "true") so Docker Compose passes them through as strings.
  • Durations use Go's format, for example 5s, 2m or 1h30m.
  • Fider reads its configuration only at startup. After changing a value, run docker compose up -d to recreate the container.
  • If a required setting is missing, Fider stops with an error such as could not find environment variable named 'EMAIL_SMTP_HOST'.

Required​

VariableDefaultDescription
BASE_URL—Public URL of your site, e.g. https://feedback.example.com. Required unless HOST_MODE is multi.
DATABASE_URL—PostgreSQL connection string, e.g. postgres://user:password@host:5432/fider?sslmode=disable.
JWT_SECRET—Secret used to sign login sessions. Use a long random value and keep it private. Changing it signs everyone out.
EMAIL_NOREPLY—"From" address for all emails Fider sends.

Email​

Fider picks the provider automatically: Mailgun if EMAIL_MAILGUN_API is set, otherwise Amazon SES if EMAIL_AWSSES_ACCESS_KEY_ID is set, otherwise SMTP. To choose one explicitly, set EMAIL.

VariableDefaultDescription
EMAILautoEmail provider: smtp, mailgun or awsses.
EMAIL_ALLOWLIST—Regular expression. When set, Fider only sends to addresses that match it, e.g. @example\.com$. Takes precedence over EMAIL_BLOCKLIST.
EMAIL_BLOCKLIST—Regular expression. Fider never sends to addresses that match it.

SMTP

VariableDefaultDescription
EMAIL_SMTP_HOST—SMTP server hostname. Required when using SMTP.
EMAIL_SMTP_PORT—SMTP server port, usually 587 (STARTTLS) or 465 (implicit TLS). Required when using SMTP.
EMAIL_SMTP_USERNAME—Username, if your server requires authentication.
EMAIL_SMTP_PASSWORD—Password, if your server requires authentication.
EMAIL_SMTP_ENABLE_STARTTLStrueUpgrade the connection with STARTTLS when the server supports it.
EMAIL_SMTP_ENABLE_IMPLICIT_TLSfalseConnect over TLS from the start (SMTPS). Set this to true when using port 465.

Mailgun

VariableDefaultDescription
EMAIL_MAILGUN_API—Mailgun API key.
EMAIL_MAILGUN_DOMAIN—Your Mailgun sending domain.
EMAIL_MAILGUN_REGIONUSUS or EU, matching the region of your Mailgun account.

Amazon SES

VariableDefaultDescription
EMAIL_AWSSES_REGION—AWS region, e.g. us-east-1.
EMAIL_AWSSES_ACCESS_KEY_ID—AWS access key ID.
EMAIL_AWSSES_SECRET_ACCESS_KEY—AWS secret access key.

File storage​

Files such as uploaded images and logos are stored in the database by default. For larger sites, you can move them to the filesystem or to S3-compatible storage.

VariableDefaultDescription
BLOB_STORAGEsqlWhere to store files: sql (in PostgreSQL), fs (on disk) or s3.
BLOB_STORAGE_FS_PATH—Folder to store files in when BLOB_STORAGE is fs. Mount it as a volume, or files are lost when the container is recreated.
BLOB_STORAGE_S3_ENDPOINT_URL—S3 endpoint, e.g. https://s3.us-east-1.amazonaws.com, or the URL of an S3-compatible service such as MinIO or Cloudflare R2. Required when using S3.
BLOB_STORAGE_S3_REGION—S3 region.
BLOB_STORAGE_S3_ACCESS_KEY_ID—S3 access key ID.
BLOB_STORAGE_S3_SECRET_ACCESS_KEY—S3 secret access key.
BLOB_STORAGE_S3_BUCKET—Bucket name. Required when using S3.

Changing BLOB_STORAGE doesn't move files that are already stored. Choose your storage before you upload anything important.

HTTPS​

See How to enable TLS/SSL for full instructions.

VariableDefaultDescription
SSL_AUTOfalseGet certificates automatically from Let's Encrypt. Fider must be reachable directly on ports 80 and 443, not behind a proxy.
SSL_CERT—Certificate file name, relative to /app/etc.
SSL_CERT_KEY—Private key file name, relative to /app/etc.

Server​

VariableDefaultDescription
PORT3000Port Fider listens on inside the container. If you change it, update your ports: mapping to match.
HOSTall interfacesAddress Fider binds to.
HTTP_READ_TIMEOUT5sMaximum time to read an incoming request.
HTTP_WRITE_TIMEOUT10sMaximum time to write a response.
HTTP_IDLE_TIMEOUT120sHow long to keep idle keep-alive connections open.
CDN_HOST—Serve static assets and uploaded files from this host instead of BASE_URL, e.g. cdn.example.com.

Database​

VariableDefaultDescription
DATABASE_MAX_OPEN_CONNS4Maximum number of open connections to PostgreSQL.
DATABASE_MAX_IDLE_CONNS2Maximum number of idle connections kept in the pool.

Sign-up and sign-in​

VariableDefaultDescription
SIGNUP_DISABLEDfalseDisable the page used to create a new site. Useful after setup, and in multi-tenant mode to stop anyone creating new boards. This doesn't stop people signing in to an existing site.
OAUTH_GOOGLE_CLIENTID / OAUTH_GOOGLE_SECRET—Enable "Sign in with Google" for all sites. See Configuring OAuth.
OAUTH_GITHUB_CLIENTID / OAUTH_GITHUB_SECRET—Enable "Sign in with GitHub" for all sites.
OAUTH_FACEBOOK_APPID / OAUTH_FACEBOOK_SECRET—Enable "Sign in with Facebook" for all sites.

Other OAuth providers (for example Microsoft, Keycloak or Authentik) are configured in the Fider admin area rather than with environment variables. See Configuring OAuth.

Features and security​

VariableDefaultDescription
LOCALEenDefault language for new sites, e.g. de, fr, pt-BR. Admins can change it later in Site Settings.
POST_CREATION_WITH_TAGS_ENABLEDfalseLet users add tags when they submit a new post. Regular users can only choose public tags.
ALLOW_ALLOWED_SCHEMEStrueLet admins allow extra link schemes (such as vscode://) in post content under Advanced Settings. Set to false to allow only the built-in safe schemes.
ALLOW_PRIVATE_NETWORK_TARGETSfalseAllow webhooks and custom OAuth providers to call private or internal addresses (e.g. localhost, 10.x.x.x, 192.168.x.x or another container). This is blocked by default for security. Enable it if you use a self-hosted OAuth provider or webhook receiver on your own network.
WEBHOOK_DISABLE_ON_FAILUREtrueAutomatically disable a webhook after it fails. Set to false to keep failing webhooks enabled.
SEARCH_NOISE_WORDSbuilt-in listCommon words that are ignored when Fider looks for similar posts, separated by the pipe character, e.g. add|support|feature. Setting this replaces the built-in list.

Logging and monitoring​

VariableDefaultDescription
LOG_LEVELINFOMinimum level to log: DEBUG, INFO, WARN or ERROR.
LOG_CONSOLEtrueWrite logs to the console (visible with docker compose logs app).
LOG_STRUCTUREDfalseWrite logs as JSON, for log collectors such as Loki or Elasticsearch.
LOG_SQLtrueAlso store logs in the logs table in PostgreSQL.
LOG_FILEfalseAlso write logs to a file.
LOG_FILE_OUTPUTlogs/output.logLog file path, relative to /app.
METRICS_ENABLEDfalseExpose Prometheus metrics on a separate port.
METRICS_PORT4000Port for the metrics server.
METRICS_HOSTall interfacesAddress the metrics server binds to.
GOOGLE_ANALYTICS—Google Analytics 4 Measurement ID, e.g. G-XXXXXXXXXX. Old Universal Analytics IDs (UA-...) no longer work, and Fider logs a warning at startup if it finds one.

When GOOGLE_ANALYTICS is set, Google Analytics stores its own _ga cookies in visitors' browsers, so you may need a cookie notice for your site. Fider sends a page view on each page load, plus events such as post_vote and comment_create, each with a tenant parameter holding the site's subdomain. By default, GA4's Enhanced Measurement also counts a page view each time the address changes without a reload (for example when filtering posts or opening a post), so you can turn off Page changes based on browser history events in your GA4 property if you'd rather count only full page loads.

Maintenance mode​

VariableDefaultDescription
MAINTENANCEfalseShow a maintenance page to all visitors instead of the site.
MAINTENANCE_MESSAGE—Message shown on the maintenance page.
MAINTENANCE_UNTIL—Free text telling visitors when you expect to be back, e.g. 14:00 UTC.

Multi-tenant​

VariableDefaultDescription
HOST_MODEsingleSet to multi to host several feedback boards on subdomains.
HOST_DOMAIN—Base domain for subdomains, e.g. feedback.example.com. Only used when HOST_MODE is multi. Don't set it in single mode.

See Multi-Tenant Hosting for details.

note

You might see other variables in the Fider source code, such as STRIPE_*, USER_LIST_* and GO_ENV. They are used by the hosted service at fider.io or for development, and you don't need to set them when self-hosting.

Mounting the etc folder​

Some features read files from /app/etc inside the container:

  • TLS certificates for SSL_CERT and SSL_CERT_KEY
  • privacy.md and terms.md to show legal pages

To use them, put the files in /var/fider/etc on your server and mount the folder:

  app:
volumes:
- /var/fider/etc:/app/etc

Updating Fider​

To update to the latest version, run:

docker compose pull
docker compose up -d

Fider runs any database migrations automatically when it starts. We recommend backing up your database before updating. Check the release notes for breaking changes.

Use a testing SMTP server​

If you don't have an SMTP server and just want to test, you can use MailHog. Add a new service to your docker-compose.yml, and configure it:

  app:
environment:
# use this EMAIL config:
EMAIL_SMTP_HOST: mailhog
EMAIL_SMTP_PORT: 1025

# add this service:
mailhog:
image: mailhog/mailhog
restart: always
ports:
- "8025:8025"

Then restart docker compose. You can now browse to http://localhost:8025 and read mails sent by fider, especially the sign-in link.

Secure Fider with HTTPS​

When exposing Fider to the internet, we strongly recommend setting up HTTPS. See How to enable TLS/SSL for the different ways to do it.

F.A.Q.​

I have submitted the installation form, but I haven't got any confirmation email​

Start with the obvious: check your spam folder. If the email isn't there, check your Fider logs (docker compose logs app) for errors. Most likely your email configuration is wrong. If you set EMAIL_ALLOWLIST or EMAIL_BLOCKLIST, check that they aren't blocking your address.

Once you've sorted your email config, in Fider you can resend the code to continue.

If you'd rather reset everything and start again, the easiest way is to delete your tenant from the database with this SQL:

TRUNCATE TABLE tenants RESTART IDENTITY CASCADE;.

danger

This SQL command will permanently delete your tenant and all associated data, including users, posts, votes, and comments. This action cannot be undone. Only use this if you want to completely reset your Fider instance.

BASE_URL doesn't match the address people use to reach Fider. Set it to your full public URL, including https://, and restart.

My webhook or OAuth provider fails with "targets a private or internal network address"​

By default, Fider blocks webhooks and custom OAuth providers from calling internal addresses. This protects your network. If the target is a service you trust on your own network, set ALLOW_PRIVATE_NETWORK_TARGETS: "true".