How to self host nitter on docker compose

Nitter lets you browser twitter with privacy in mind and with actually more features like RSS feeds. It's a proxy for twitter so you can follow the people you like on twitter without actually giving up your data

It's easy to host it but before I start I will assume that: * You are running debian 11 * You already have a VPS: * Your linux distro is up-to-date (sudo apt update && sudo apt upgrade) * You have a domain name: * Have sudo access or root account * Already installed docker and docker-compose: * Already installed Nginx: * Already have a reverse proxy conf file: * Already have certbot to issue cert:

Changes in DNS (domain side)

You really do not need to add any dns entries except if you want to create subdomain for this container then you go in your domain's dns panel and add either CNAME entry that looks like and make it's target the root domain or A entry with and make it's target the IP of your VPS

nitter docker-compose file

We need a docker-compose.yml file so we can start nitter, for me I use this file:

version: "3"


    image: zedeus/nitter:latest
    container_name: nitter
      - "" # Replace with "8080:8080" if you don't use a reverse proxy
      - ./nitter.conf:/src/nitter.conf:ro
      - nitter-redis
    restart: unless-stopped

    image: redis:6-alpine
    container_name: nitter-redis
    command: redis-server --save 60 1 --loglevel warning
      - nitter-redis:/data
    restart: unless-stopped


Optional stuff to change: The IP and port number for nitter (so we can use it later for nginx to reverse proxy it) ./nitter.conf: Where and what name our config for nitter will be saved

If you want to see a real world example of nitter.conf file:

address = ""
port = 8080
https = false  # disable to enable cookies when not using https
httpMaxConnections = 100
staticDir = "./public"
title = "nitter"
hostname = ""

listMinutes = 240  # how long to cache list info (not the tweets, so keep it high)
rssMinutes = 10  # how long to cache rss queries
redisHost = "nitter-redis" # Change to "nitter-redis" if using docker-compose
redisPort = 6379
redisPassword = ""
redisConnections = 20  # connection pool size
redisMaxConnections = 30
# max, new connections are opened when none are available, but if the pool size
# goes above this, they're closed when released. don't worry about this unless
# you receive tons of requests per second

hmacKey = "13441753" # random key for cryptographic signing of video urls
base64Media = true # use base64 encoding for proxied media urls
enableRSS = true  # set this to false to disable RSS feeds
enableDebug = false  # enable request logs and debug endpoints
proxy = ""  # http/https url, SOCKS proxies are not supported
proxyAuth = ""
tokenCount = 10
# minimum amount of usable tokens. tokens are used to authorize API requests,
# but they expire after ~1 hour, and have a limit of 187 requests.
# the limit gets reset every 15 minutes, and the pool is filled up so there's
# always at least $tokenCount usable tokens. again, only increase this if
# you receive major bursts all the time

# Change default preferences here, see src/prefs_impl.nim for a complete list
theme = "Nitter"
replaceTwitter = ""
replaceYouTube = ""
replaceReddit = ""
replaceInstagram = ""
proxyVideos = false
hlsPlayback = true
infiniteScroll = true

NOTE: you do not change port here in nitter's config. Docker and image inside it think of them as separate thing so port we changed in docker-compose is what is actually exposed to nginx and port in nitter's config is just a more like of a mapped port so docker can look for 8080 and assign it for our port we added in docker-compose file

Spin it up!

Now after we done editing, and everything is cool. We need to run our container so just run:

docker-compose up -d

the -d option does not let docker post logs of running application but if you want to see logs you can run:

sudo docker-compose logs -f -t

To check if there any weird behaviors or errors


Now after we make sure it's running well. We need to serve it over the internet (called reverse proxy) so without much talk, here is our server block for nitter:

server {
        listen [::]:80;
        listen 80;
        server_name [domain name] ; ;

       location / {
               include /etc/nginx/reverse-proxy.conf;

server_name: Change this to match domain name of nitter include: is our reverse proxy file proxy_pass: the IP and port of our running docker image

After this you should be up and running for nitter! :) just do not forget to run certbot --nginx to make it secure with https://

Update it

Of course after some time the image will be outdated and you need to update and what I love about docker that it's easy to update, really just to do it run:

docker-compose down && docker-compose pull && docker-compose up -d

What it does is: 1) Stops the container, 2) Pull last update (download last update) and 3) Re-run the container back!


If you use firewall (ufw for example) you really do not need any ports other than 443 and 80 as we use nginx reverse proxy

#howto #selfhost #docker