mirror of
http://git.nowherejezfoltodf4jiyl6r56jnzintap5vyjlia7fkirfsnfizflqd.onion/nihilist/selfhosting-blogposts.git
synced 2025-05-16 12:16:59 +00:00
349 lines
13 KiB
Markdown
349 lines
13 KiB
Markdown
---
|
|
search:
|
|
exclude: true
|
|
---
|
|
# nitter Setup
|
|
|
|

|
|
|
|
In this tutorial we're going to setup nitter, a privacy front end to browse twitter without all the trackers.
|
|
|
|
## **Initial Setup**
|
|
|
|
Clone the repository and start the docker-compose:
|
|
|
|
|
|
[ nowhere.moe ] [ /dev/pts/1 ] [/srv/nitter]
|
|
→ apt install nim docker.io docker-compose libsass-dev libpcre3
|
|
|
|
[ nowhere.moe ] [ /dev/pts/1 ] [/srv]
|
|
→ git clone https://github.com/zedeus/nitter
|
|
Cloning into 'nitter'...
|
|
remote: Enumerating objects: 6639, done.
|
|
remote: Counting objects: 100% (163/163), done.
|
|
remote: Compressing objects: 100% (118/118), done.
|
|
remote: Total 6639 (delta 87), reused 97 (delta 45), pack-reused 6476
|
|
Receiving objects: 100% (6639/6639), 5.26 MiB | 1.81 MiB/s, done.
|
|
Resolving deltas: 100% (4852/4852), done.
|
|
|
|
[ nowhere.moe ] [ /dev/pts/1 ] [/srv]
|
|
→ cd nitter
|
|
|
|
[ nowhere.moe ] [ /dev/pts/1 ] [/srv/nitter]
|
|
→ docker build -t nitter:latest .
|
|
|
|
Sending build context to Docker daemon 6.428MB
|
|
Step 1/18 : FROM nimlang/nim:1.6.10-alpine-regular as nim
|
|
1.6.10-alpine-regular: Pulling from nimlang/nim
|
|
213ec9aee27d: Pull complete
|
|
071ba9e2da5d: Pull complete
|
|
8c05e9a65d0e: Pull complete
|
|
|
|
[...]
|
|
|
|
Step 17/18 : USER nitter
|
|
---> Running in b9cbc6b2d0f5
|
|
Removing intermediate container b9cbc6b2d0f5
|
|
---> d887fd7e9c0f
|
|
Step 18/18 : CMD ./nitter
|
|
---> Running in 0dca3c6f9ba3
|
|
Removing intermediate container 0dca3c6f9ba3
|
|
---> 24ad9b89ab85
|
|
Successfully built 24ad9b89ab85
|
|
Successfully tagged nitter:latest
|
|
|
|
[ nowhere.moe ] [ /dev/pts/1 ] [/srv/nitter]
|
|
→ apt install nim
|
|
|
|
[ nowhere.moe ] [ /dev/pts/1 ] [/srv/nitter]
|
|
→ nimble build -d:release
|
|
Verifying dependencies for nitter@0.1.0
|
|
Prompt: No local packages.json found, download it from internet? [y/N]
|
|
Answer: y
|
|
Downloading Official package list
|
|
Success Package list downloaded.
|
|
Installing jester@#baca3f
|
|
Downloading https://github.com/dom96/jester using git
|
|
Verifying dependencies for jester@#baca3f
|
|
|
|
[...]
|
|
|
|
[ nowhere.moe ] [ /dev/pts/1 ] [/srv/nitter]
|
|
→ nimble scss
|
|
|
|
[ nowhere.moe ] [ /dev/pts/1 ] [/srv/nitter]
|
|
→ nimble md
|
|
|
|
[ nowhere.moe ] [ /dev/pts/1 ] [/srv/nitter]
|
|
→ cp nitter.example.conf nitter.conf
|
|
|
|
[ nowhere.moe ] [ /dev/pts/1 ] [/srv/nitter]
|
|
→ cat nitter.conf
|
|
[Server]
|
|
hostname = "nitter.nowhere.moe" # for generating links, change this to your own domain/ip
|
|
title = "nitter"
|
|
address = "0.0.0.0"
|
|
port = 8080
|
|
https = false # disable to enable cookies when not using https
|
|
httpMaxConnections = 100
|
|
staticDir = "./public"
|
|
|
|
[Cache]
|
|
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 # minimum open connections in pool
|
|
redisMaxConnections = 30
|
|
# 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
|
|
|
|
[Config]
|
|
hmacKey = "aoQu6le1IQueut8hei3U" # random key for cryptographic signing of video urls # use pwgen 20 1 to generate it
|
|
base64Media = false # 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 (/.tokens)
|
|
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 500 requests per endpoint.
|
|
# the limits reset every 15 minutes, and the pool is filled up so there's
|
|
# always at least `tokenCount` usable tokens. only increase this if you receive
|
|
# major bursts all the time and don't have a rate limiting setup via e.g. nginx
|
|
|
|
# Change default preferences here, see src/prefs_impl.nim for a complete list
|
|
[Preferences]
|
|
theme = "Nitter"
|
|
replaceTwitter = "nitter.nowhere.moe"
|
|
replaceYouTube = "iv.nowhere.moe"
|
|
replaceReddit = "teddit.net"
|
|
proxyVideos = true
|
|
hlsPlayback = false
|
|
infiniteScroll = false
|
|
|
|
[ nowhere.moe ] [ /dev/pts/1 ] [/srv/nitter]
|
|
→ cat docker-compose.yml
|
|
version: "3"
|
|
|
|
services:
|
|
|
|
nitter:
|
|
image: zedeus/nitter:latest
|
|
container_name: nitter
|
|
ports:
|
|
- "127.0.0.1:8080:8080" # Replace with "8080:8080" if you don't use a reverse proxy
|
|
volumes:
|
|
- ./nitter.conf:/src/nitter.conf:Z,ro
|
|
depends_on:
|
|
- nitter-redis
|
|
restart: unless-stopped
|
|
healthcheck:
|
|
test: wget -nv --tries=1 --spider http://127.0.0.1:8080/Jack/status/20 || exit 1
|
|
interval: 30s
|
|
timeout: 5s
|
|
retries: 2
|
|
user: "998:998"
|
|
read_only: true
|
|
security_opt:
|
|
- no-new-privileges:true
|
|
cap_drop:
|
|
- ALL
|
|
|
|
nitter-redis:
|
|
image: redis:6-alpine
|
|
container_name: nitter-redis
|
|
command: redis-server --save 60 1 --loglevel warning
|
|
volumes:
|
|
- nitter-redis:/data
|
|
restart: unless-stopped
|
|
healthcheck:
|
|
test: redis-cli ping
|
|
interval: 30s
|
|
timeout: 5s
|
|
retries: 2
|
|
user: "999:1000"
|
|
read_only: true
|
|
security_opt:
|
|
- no-new-privileges:true
|
|
cap_drop:
|
|
- ALL
|
|
|
|
volumes:
|
|
nitter-redis:
|
|
|
|
[ nowhere.moe ] [ /dev/pts/1 ] [/srv/nitter]
|
|
→ docker-compose down
|
|
Stopping nitter ... done
|
|
Stopping nitter-redis ... done
|
|
Removing nitter ... done
|
|
Removing nitter-redis ... done
|
|
Removing network nitter_default
|
|
|
|
[ nowhere.moe ] [ /dev/pts/1 ] [/srv/nitter]
|
|
→ docker-compose up -d
|
|
Creating network "nitter_default" with the default driver
|
|
Creating nitter-redis ... done
|
|
Creating nitter ... done
|
|
|
|
|
|
|
|
then you can check your service is up on port 8080:
|
|
|
|
|
|
[ nowhere.moe ] [ /dev/pts/1 ] [/srv/nitter]
|
|
→ docker container ls
|
|
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
|
3582cdcf9687 zedeus/nitter:latest "/bin/sh -c ./nitter" 3 minutes ago Up 3 minutes (healthy) 127.0.0.1:8080->8080/tcp nitter
|
|
1b9a40a33d83 redis:6-alpine "docker-entrypoint.s…" 3 minutes ago Up 3 minutes (healthy) 6379/tcp nitter-redis
|
|
|
|
|
|
|
|
Then setup the reverse nginx proxy:
|
|
|
|
|
|
[ nowhere.moe ] [ /dev/pts/1 ] [/srv/nitter]
|
|
→ vim /etc/nginx/sites-available/nitter.nowhere.moe.conf
|
|
|
|
[ nowhere.moe ] [ /dev/pts/1 ] [/srv/nitter]
|
|
→ cat /etc/nginx/sites-available/nitter.nowhere.moe.conf
|
|
server {
|
|
listen 443 ssl;
|
|
server_name nitter.nowhere.moe;
|
|
|
|
ssl_certificate /etc/acme/certs/nitter.nowhere.moe/fullchain.cer;
|
|
ssl_certificate_key /etc/acme/certs/nitter.nowhere.moe/iv.nowhere.moe.key;
|
|
|
|
|
|
ssl_protocols TLSv1.3 TLSv1.2 TLSv1.1 TLSv1;
|
|
ssl_prefer_server_ciphers on;
|
|
ssl_ciphers EECDH+AESGCM:EDH+AESGCM;
|
|
ssl_ecdh_curve secp384r1;
|
|
ssl_session_timeout 10m;
|
|
ssl_session_cache shared:SSL:10m;
|
|
ssl_session_tickets off;
|
|
ssl_stapling on;
|
|
ssl_stapling_verify on;
|
|
|
|
# Security Headers
|
|
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
|
|
add_header Content-Security-Policy "default-src 'none'; script-src 'self' 'unsafe-inline'; img-src 'self'; style-src 'self' 'unsafe-inline'; font-src 'self'; object-src 'none'; media-src 'self' blob: video.twimg.com; worker-src 'self' blob:; base-uri 'self'; form-action 'self'; frame-ancestors 'self'; connect-src 'self' https://*.twimg.com; manifest-src 'self'";
|
|
add_header X-Content-Type-Options nosniff;
|
|
add_header X-Frame-Options DENY;
|
|
add_header X-XSS-Protection "1; mode=block";
|
|
|
|
location / {
|
|
proxy_pass http://localhost:YOUR_NITTER_PORT;
|
|
}
|
|
|
|
location = /robots.txt {
|
|
add_header Content-Type text/plain;
|
|
return 200 "User-agent: *\nDisallow: /\n";
|
|
}
|
|
}
|
|
|
|
[ nowhere.moe ] [ /dev/pts/1 ] [/srv/nitter]
|
|
→ bash
|
|
root@Datura /srv/nitter # systemctl stop nginx
|
|
|
|
root@Datura /srv/nitter # acme.sh --issue --standalone -d nitter.nowhere.moe -k 4096
|
|
|
|
[ nowhere.moe ] [ /dev/pts/1 ] [/etc/nginx/sites-available]
|
|
→ ln -s /etc/nginx/sites-available/nitter.nowhere.moe.conf /etc/nginx/sites-enabled
|
|
|
|
root@Datura /srv/nitter # systemctl start nginx
|
|
|
|
[ nowhere.moe ] [ /dev/pts/1 ] [/srv/nitter]
|
|
→ systemctl status nginx
|
|
● nginx.service - A high performance web server and a reverse proxy server
|
|
Loaded: loaded (/lib/systemd/system/nginx.service; enabled; preset: enabled)
|
|
Active: active (running) since Sat 2023-07-15 22:55:17 CEST; 7min ago
|
|
Docs: man:nginx(8)
|
|
Process: 168567 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
|
|
Process: 168568 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
|
|
Main PID: 168569 (nginx)
|
|
Tasks: 13 (limit: 77000)
|
|
Memory: 15.9M
|
|
CPU: 776ms
|
|
CGroup: /system.slice/nginx.service
|
|
├─168569 "nginx: master process /usr/sbin/nginx -g daemon on; master_process on;"
|
|
├─169429 "nginx: worker process"
|
|
├─169430 "nginx: worker process"
|
|
├─169431 "nginx: worker process"
|
|
├─169432 "nginx: worker process"
|
|
├─169433 "nginx: worker process"
|
|
├─169434 "nginx: worker process"
|
|
├─169435 "nginx: worker process"
|
|
├─169436 "nginx: worker process"
|
|
├─169437 "nginx: worker process"
|
|
├─169438 "nginx: worker process"
|
|
├─169439 "nginx: worker process"
|
|
└─169440 "nginx: worker process"
|
|
|
|
Jul 15 22:55:17 Datura systemd[1]: Starting nginx.service - A high performance web server and a reverse proxy server...
|
|
Jul 15 22:55:17 Datura systemd[1]: Started nginx.service - A high performance web server and a reverse proxy server.
|
|
|
|
|
|
|
|
Then test to see if your website renders fine:
|
|
|
|

|
|
|
|
To have it available on tor you can use the following nginx config:
|
|
|
|
|
|
[ nowhere.moe ] [ /dev/pts/1 ] [/etc/nginx/sites-available]
|
|
→ cat nitter.nowhere.moe.conf
|
|
server {
|
|
listen 443 ssl;
|
|
server_name nitter.nowhere.moe;
|
|
|
|
ssl_certificate /etc/acme/certs/nitter.nowhere.moe/nitter.nowhere.moe.cer;
|
|
ssl_certificate_key /etc/acme/certs/nitter.nowhere.moe/nitter.nowhere.moe.key;
|
|
|
|
######## TOR CHANGES ########
|
|
listen 4443;
|
|
listen [::]:4443;
|
|
server_name nitter.daturab6drmkhyeia4ch5gvfc2f3wgo6bhjrv3pz6n7kxmvoznlkq4yd.onion;
|
|
add_header Onion-Location "http://nitter.daturab6drmkhyeia4ch5gvfc2f3wgo6bhjrv3pz6n7kxmvoznlkq4yd.onion$request_uri" always;
|
|
######## TOR CHANGES ########
|
|
|
|
|
|
ssl_protocols TLSv1.3 TLSv1.2 TLSv1.1 TLSv1;
|
|
ssl_prefer_server_ciphers on;
|
|
ssl_ciphers EECDH+AESGCM:EDH+AESGCM;
|
|
ssl_ecdh_curve secp384r1;
|
|
ssl_session_timeout 10m;
|
|
ssl_session_cache shared:SSL:10m;
|
|
ssl_session_tickets off;
|
|
ssl_stapling on;
|
|
ssl_stapling_verify on;
|
|
|
|
# Security Headers
|
|
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
|
|
add_header Content-Security-Policy "default-src 'none'; script-src 'self' 'unsafe-inline'; img-src 'self'; style-src 'self' 'unsafe-inline'; font-src 'self'; object-src 'none'; media-src 'self' blob: video.twimg.com; worker-src 'self' blob:; base-uri 'self'; form-action 'self'; frame-ancestors 'self'; connect-src 'self' https://*.twimg.com; manifest-src 'self'";
|
|
add_header X-Content-Type-Options nosniff;
|
|
add_header X-Frame-Options DENY;
|
|
add_header X-XSS-Protection "1; mode=block";
|
|
|
|
location / {
|
|
proxy_pass http://localhost:8080;
|
|
}
|
|
|
|
location = /robots.txt {
|
|
add_header Content-Type text/plain;
|
|
return 200 "User-agent: *\nDisallow: /\n";
|
|
}
|
|
}
|
|
|
|
[ nowhere.moe ] [ /dev/pts/1 ] [/etc/nginx/sites-available]
|
|
→ nginx -s reload
|
|
|
|
|
|
|
|

|
|
|
|
And thats it! now last step is to contribute to the overall [list of instances](https://github.com/zedeus/nitter/wiki/Instances) by sending a request to get your instance listed publicly [here](https://github.com/zedeus/nitter/issues/947).
|
|
|