Hosting on Docker
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:
- An SMTP server
- A Mailgun account
- Amazon SES
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.

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
trueorfalse. Quote them in YAML (SSL_AUTO: "true") so Docker Compose passes them through as strings. - Durations use Go's format, for example
5s,2mor1h30m. - Fider reads its configuration only at startup. After changing a value, run
docker compose up -dto 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​
| Variable | Default | Description |
|---|---|---|
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.
| Variable | Default | Description |
|---|---|---|
EMAIL | auto | Email 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
| Variable | Default | Description |
|---|---|---|
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_STARTTLS | true | Upgrade the connection with STARTTLS when the server supports it. |
EMAIL_SMTP_ENABLE_IMPLICIT_TLS | false | Connect over TLS from the start (SMTPS). Set this to true when using port 465. |
Mailgun
| Variable | Default | Description |
|---|---|---|
EMAIL_MAILGUN_API | — | Mailgun API key. |
EMAIL_MAILGUN_DOMAIN | — | Your Mailgun sending domain. |
EMAIL_MAILGUN_REGION | US | US or EU, matching the region of your Mailgun account. |
Amazon SES
| Variable | Default | Description |
|---|---|---|
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.
| Variable | Default | Description |
|---|---|---|
BLOB_STORAGE | sql | Where 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.
| Variable | Default | Description |
|---|---|---|
SSL_AUTO | false | Get 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​
| Variable | Default | Description |
|---|---|---|
PORT | 3000 | Port Fider listens on inside the container. If you change it, update your ports: mapping to match. |
HOST | all interfaces | Address Fider binds to. |
HTTP_READ_TIMEOUT | 5s | Maximum time to read an incoming request. |
HTTP_WRITE_TIMEOUT | 10s | Maximum time to write a response. |
HTTP_IDLE_TIMEOUT | 120s | How 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​
| Variable | Default | Description |
|---|---|---|
DATABASE_MAX_OPEN_CONNS | 4 | Maximum number of open connections to PostgreSQL. |
DATABASE_MAX_IDLE_CONNS | 2 | Maximum number of idle connections kept in the pool. |
Sign-up and sign-in​
| Variable | Default | Description |
|---|---|---|
SIGNUP_DISABLED | false | Disable 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​
| Variable | Default | Description |
|---|---|---|
LOCALE | en | Default language for new sites, e.g. de, fr, pt-BR. Admins can change it later in Site Settings. |
POST_CREATION_WITH_TAGS_ENABLED | false | Let users add tags when they submit a new post. Regular users can only choose public tags. |
ALLOW_ALLOWED_SCHEMES | true | Let 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_TARGETS | false | Allow 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_FAILURE | true | Automatically disable a webhook after it fails. Set to false to keep failing webhooks enabled. |
SEARCH_NOISE_WORDS | built-in list | Common 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​
| Variable | Default | Description |
|---|---|---|
LOG_LEVEL | INFO | Minimum level to log: DEBUG, INFO, WARN or ERROR. |
LOG_CONSOLE | true | Write logs to the console (visible with docker compose logs app). |
LOG_STRUCTURED | false | Write logs as JSON, for log collectors such as Loki or Elasticsearch. |
LOG_SQL | true | Also store logs in the logs table in PostgreSQL. |
LOG_FILE | false | Also write logs to a file. |
LOG_FILE_OUTPUT | logs/output.log | Log file path, relative to /app. |
METRICS_ENABLED | false | Expose Prometheus metrics on a separate port. |
METRICS_PORT | 4000 | Port for the metrics server. |
METRICS_HOST | all interfaces | Address 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​
| Variable | Default | Description |
|---|---|---|
MAINTENANCE | false | Show 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​
| Variable | Default | Description |
|---|---|---|
HOST_MODE | single | Set 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.
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_CERTandSSL_CERT_KEY privacy.mdandterms.mdto 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;.
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.
Links in emails point to the wrong address​
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".