A => .gitmodules +3 -0
@@ 1,3 @@
+[submodule "nitter/src"]
+ path = nitter/src
+ url = https://github.com/PrivacyDevel/nitter
A => dnsmasq/Dockerfile +12 -0
@@ 1,12 @@
+FROM docker.io/library/alpine:latest
+
+COPY dnsmasq.conf /etc/dnsmasq.conf
+
+RUN apk add --no-cache dnsmasq dumb-init
+
+EXPOSE 53 53/udp
+
+ENTRYPOINT ["/usr/bin/dumb-init", "--"]
+
+CMD ["dnsmasq", "--keep-in-foreground"]
+
A => dnsmasq/Makefile +14 -0
@@ 1,14 @@
+CONMAN=sudo docker
+COLORIZE=| { GREP_COLORS="ms=01;32" grep -e '.*' --color=always || true; }
+
+REGISTRY=registry.intra.dominic-ricottone.com
+IMAGE=dnsmasq
+TAG=latest
+
+image:
+ $(CONMAN) buildx build --push \
+ --platform linux/arm64,linux/amd64 \
+ --tag $(REGISTRY)/$(IMAGE):$(TAG) \
+ .
+
+.PHONY: image
A => dnsmasq/README.md +34 -0
@@ 1,34 @@
+# dnsmasq
+
+
+## Build and Deploy
+
+```
+make image
+```
+
+
+### Tags
+
+ + `latest`
+
+----
+
+## Use
+
+Can be used with any container manager toolchain.
+
+Create a hosts file in `$hostsfile`. It should look like:
+
+```
+1.2.3.4 example.com www.example.com
+```
+
+Try:
+
+```
+$conman run --detach --name dnsmasq --restart always \
+ --mount type=bind,src=$hostsfile,target=/etc/dnsmasq-hosts,readonly \
+ registry.intra.dominic-ricottone.com/dnsmasq:latest
+```
+
A => dnsmasq/dnsmasq.conf +6 -0
@@ 1,6 @@
+no-hosts
+addn-hosts=/etc/dnsmasq-hosts
+no-resolv
+server=8.8.4.4
+server=8.8.8.8
+
A => haproxy/Dockerfile +8 -0
@@ 1,8 @@
+FROM docker.io/library/haproxy:alpine
+
+COPY haproxy.cfg /usr/local/etc/haproxy/haproxy.cfg
+
+# Overriding the CMD to load all '*.cfg' files in '/usr/local/etc/haproxy.d';
+# lexical order, newer files overriding older files
+CMD ["haproxy", "-f", "/usr/local/etc/haproxy/haproxy.cfg", "-f", "/usr/local/etc/haproxy.d"]
+
A => haproxy/Makefile +14 -0
@@ 1,14 @@
+CONMAN=sudo docker
+COLORIZE=| { GREP_COLORS="ms=01;32" grep -e '.*' --color=always || true; }
+
+REGISTRY=registry.intra.dominic-ricottone.com
+IMAGE=haproxy
+TAG=latest
+
+image:
+ $(CONMAN) buildx build --push \
+ --platform linux/arm64,linux/amd64 \
+ --tag $(REGISTRY)/$(IMAGE):$(TAG) \
+ .
+
+.PHONY: image
A => haproxy/README.md +46 -0
@@ 1,46 @@
+# haproxy
+
+
+## Build and Deploy
+
+```
+make image
+```
+
+
+### Tags
+
+ + `latest`
+
+----
+
+## Use
+
+Can be used with any container manager toolchain.
+
+Create configuration files in `$confdir`. They should look like:
+
+```
+resolvers docker_dns
+ nameserver docker 127.0.0.11:53
+
+backend www_backend
+ server web1 nginx:80 check resolvers docker_dns
+
+frontend http_frontend
+ bind :8080
+ bind :8443 ssl crt /var/letsencrypt/example.com.pem alpn h2,http1.1
+ mode http
+ http-request redirect scheme https unless { ssl_fc }
+
+ default_backend web_backend
+```
+
+Try:
+
+```
+$conman run --detach --name haproxy --restart always \
+ --mount type=bind,src=$confdir,dst=/usr/local/etc/haproxy.d,readonly \
+ registry.intra.dominic-ricottone.com/haproxy:latest
+```
+
A => haproxy/haproxy.cfg +19 -0
@@ 1,19 @@
+global
+ ssl-default-bind-options ssl-min-ver TLSv1.2
+ log stdout format raw local0
+ maxconn 1024
+
+defaults
+ timeout connect 10s
+ timeout client 30s
+ timeout server 30s
+ mode http
+ log global
+ default-server init-addr none
+
+#frontend stats_frontend
+# bind :8404
+# http-request use-service prometheus-exporter if { path /metrics }
+# stats enable
+# stats uri /stats
+# stats refresh 10s
A => nginx/Dockerfile +5 -0
@@ 1,5 @@
+FROM docker.io/library/nginx:alpine
+
+COPY *.conf /etc/nginx/
+COPY error_pages.d/ /etc/nginx/conf.d/error_pages.d/
+
A => nginx/Makefile +14 -0
@@ 1,14 @@
+CONMAN=sudo docker
+COLORIZE=| { GREP_COLORS="ms=01;32" grep -e '.*' --color=always || true; }
+
+REGISTRY=registry.intra.dominic-ricottone.com
+IMAGE=nginx
+TAG=latest
+
+image:
+ $(CONMAN) buildx build --push \
+ --platform linux/arm64,linux/amd64 \
+ --tag $(REGISTRY)/$(IMAGE):$(TAG) \
+ .
+
+.PHONY: image
A => nginx/README.md +149 -0
@@ 1,149 @@
+# nginx
+
+
+## Build and Deploy
+
+```
+make image
+```
+
+
+### Tags
+
+ + `latest`
+
+----
+
+## Use
+
+Can be used with any container manager toolchain.
+
+Create server files in `$confdir`. They should look like:
+
+```
+server {
+ listen 80 default_server;
+ server_name _;
+
+ location / {
+ root /usr/share/nginx/html;
+ }
+}
+```
+
+Try:
+
+```
+$conman run --detach --name nginx --restart always \
+ --mount type=bind,src=$confdir,dst=/etc/nginx/conf.d,readonly \
+ registry.intra.dominic-ricottone.com/nginx:latest
+```
+
+----
+
+## How to use...
+
+
+### errorpages.conf
+
+`errorpages.conf` adds custom error pages and locations.
+Consider adding these to all server.
+
+```
+server {
+ list 80;
+ server_name example.com;
+
+ include errorpages.conf;
+}
+```
+
+
+### headers.conf
+
+`headers.conf` adds a set of very common and generally useful headers.
+Consider adding these to all locations except on the default server,
+and any internal redirect locations.
+
+```
+location / {
+ include headers.conf;
+}
+```
+
+
+### proxy.conf
+
+`proxy.conf` adds a set of headers and enables a set of options that are
+useful for redirects and proxies.
+
+```
+location / {
+ proxy_read_timeout 300s;
+ proxy_connect_timeout 75s;
+ proxy_pass http://localhost:8080;
+ include proxy.conf;
+}
+```
+
+
+### fastcgi.conf
+
+`uwsgi.conf` adds a set of headers and enables a set of options that are
+useful for FastCGI proxies.
+
+```
+location / {
+ include fastcgi.conf;
+ fastcgi_param SCRIPT_FILENAME /app.cgi;
+ fastcgi_param PATH_INFO $uri;
+ fastcgi_param QUERY_STRING $args;
+ fastcgi_param HTTP_HOST $server_name;
+ fastcgi_pass localhost:9000;
+}
+```
+
+
+
+### uwsgi.conf
+
+`uwsgi.conf` adds a set of headers and enables a set of options that are
+useful for uWSGI proxies.
+
+```
+location / {
+ include uwsgi.conf;
+ uwsgi_pass localhost:9000;
+}
+```
+
+
+### graphql.conf
+
+`graphql.conf` adds a set of headers and enables a set of options that are
+useful for GraphQL proxies.
+
+```
+location /query {
+ proxy_read_timeout 300s;
+ proxy_connect_timeout 75s;
+ proxy_pass http://localhost:8081;
+ include graphql.conf;
+}
+```
+
+
+### letsencrypt.conf
+
+`letsencrypt.conf` adds a location for `certbot(8)` integration.
+
+```
+server {
+ listen 80;
+ server_name example.com;
+
+ include letsencrypt.conf;
+}
+```
+
+
A => nginx/error_pages.d/403.html +12 -0
@@ 1,12 @@
+<!doctype html>
+<html lang="en">
+<head>
+ <meta charset="utf-8" name="viewport" content="width=device-width, initial-scale=1">
+ <title>403 - Forbidden</title>
+</head>
+<body>
+ <h1>403 - Forbidden</h1>
+ <p>You reached an instance of `nginx(8)`</p>
+</body>
+</html>
+
A => nginx/error_pages.d/404.html +12 -0
@@ 1,12 @@
+<!doctype html>
+<html lang="en">
+<head>
+ <meta charset="utf-8" name="viewport" content="width=device-width, initial-scale=1">
+ <title>404 - Not Found</title>
+</head>
+<body>
+ <h1>404 - Not Found</h1>
+ <p>You reached an instance of `nginx(8)`</p>
+</body>
+</html>
+
A => nginx/error_pages.d/500.html +12 -0
@@ 1,12 @@
+<!doctype html>
+<html lang="en">
+<head>
+ <meta charset="utf-8" name="viewport" content="width=device-width, initial-scale=1">
+ <title>500 - Internal Server Error</title>
+</head>
+<body>
+ <h1>500 - Internal Server Error</h1>
+ <p>You reached an instance of `nginx(8)`</p>
+</body>
+</html>
+
A => nginx/error_pages.d/502.html +12 -0
@@ 1,12 @@
+<!doctype html>
+<html lang="en">
+<head>
+ <meta charset="utf-8" name="viewport" content="width=device-width, initial-scale=1">
+ <title>502 - Bad Gateway</title>
+</head>
+<body>
+ <h1>502 - Bad Gateway</h1>
+ <p>You reached an instance of `nginx(8)`</p>
+</body>
+</html>
+
A => nginx/error_pages.d/503.html +12 -0
@@ 1,12 @@
+<!doctype html>
+<html lang="en">
+<head>
+ <meta charset="utf-8" name="viewport" content="width=device-width, initial-scale=1">
+ <title>503 - Service Unavailable</title>
+</head>
+<body>
+ <h1>503 - Service Unavailable</h1>
+ <p>You reached an instance of `nginx(8)`</p>
+</body>
+</html>
+
A => nginx/error_pages.d/504.html +12 -0
@@ 1,12 @@
+<!doctype html>
+<html lang="en">
+<head>
+ <meta charset="utf-8" name="viewport" content="width=device-width, initial-scale=1">
+ <title>504 - Gateway Timeout</title>
+</head>
+<body>
+ <h1>504 - Gateway Timeout</h1>
+ <p>You reached an instance of `nginx(8)`</p>
+</body>
+</html>
+
A => nginx/errorpages.conf +36 -0
@@ 1,36 @@
+error_page 403 /403.html;
+location = /403.html {
+ root /etc/nginx/conf.d/error_pages.d;
+ internal;
+}
+
+error_page 404 /404.html;
+location = /404.html {
+ root /etc/nginx/conf.d/error_pages.d;
+ internal;
+}
+
+error_page 500 /500.html;
+location = /500.html {
+ root /etc/nginx/conf.d/error_pages.d;
+ internal;
+}
+
+error_page 502 /502.html;
+location = /502.html {
+ root /etc/nginx/conf.d/error_pages.d;
+ internal;
+}
+
+error_page 503 /503.html;
+location = /503.html {
+ root /etc/nginx/conf.d/error_pages.d;
+ internal;
+}
+
+error_page 504 /504.html;
+location = /504.html {
+ root /etc/nginx/conf.d/error_pages.d;
+ internal;
+}
+
A => nginx/fastcgi.conf +28 -0
@@ 1,28 @@
+# mitigate crafted URLs
+fastcgi_param REDIRECT_STATUS 200;
+
+# mitigate httpoxy.com
+fastcgi_param HTTP_PROXY "";
+
+fastcgi_param QUERY_STRING $query_string;
+fastcgi_param REQUEST_METHOD $request_method;
+fastcgi_param CONTENT_TYPE $content_type;
+fastcgi_param CONTENT_LENGTH $content_length;
+
+fastcgi_param SCRIPT_NAME $fastcgi_script_name;
+fastcgi_param REQUEST_URI $request_uri;
+fastcgi_param DOCUMENT_URI $document_uri;
+fastcgi_param DOCUMENT_ROOT $document_root;
+fastcgi_param SERVER_PROTOCOL $server_protocol;
+fastcgi_param REQUEST_SCHEME $scheme;
+fastcgi_param HTTPS $https if_not_empty;
+
+fastcgi_param GATEWAY_INTERFACE CGI/1.1;
+fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
+
+fastcgi_param REMOTE_ADDR $remote_addr;
+fastcgi_param REMOTE_PORT $remote_port;
+fastcgi_param SERVER_ADDR $server_addr;
+fastcgi_param SERVER_PORT $server_port;
+fastcgi_param SERVER_NAME $server_name;
+
A => nginx/graphql.conf +18 -0
@@ 1,18 @@
+real_ip_header X-Forwarded-For;
+real_ip_recursive on;
+proxy_set_header Host $host;
+proxy_set_header X-Forwarded-Proto https;
+proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+if ($request_method = 'OPTIONS') {
+ add_header 'Access-Control-Allow-Origin' '*';
+ add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
+ add_header 'Access-Control-Allow-Headers' 'User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
+ add_header 'Access-Control-Max-Age' 1728000;
+ add_header 'Content-Type' 'text/plain; charset=utf-8';
+ add_header 'Content-Length' 0;
+ return 204;
+}
+add_header 'Access-Control-Allow-Origin' '*';
+add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
+add_header 'Access-Control-Allow-Headers' 'User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
+add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
A => +3 -0
@@ 1,3 @@
add_header X-Clacks-Overhead "GNU Terry Pratchett";
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header Permissions-Policy interest-cohort=();
A => nginx/letsencrypt.conf +6 -0
@@ 1,6 @@
+location ^~ /.well-known/acme-challenge/ {
+ allow all;
+ root /usr/share/nginx/html/letsencrypt;
+ default_type "text/plain";
+ try_files $uri =404;
+}
A => nginx/nginx.conf +36 -0
@@ 1,36 @@
+user nginx;
+worker_processes auto;
+pcre_jit on;
+error_log /var/log/nginx/error.log warn;
+pid /var/run/nginx.pid;
+include /etc/nginx/modules/*.conf;
+
+events {
+ worker_connections 1024;
+}
+
+http {
+ include /etc/nginx/mime.types;
+ default_type application/octet-stream;
+
+ server_tokens off;
+ client_max_body_size 1m;
+ sendfile on;
+ tcp_nopush on;
+ ssl_protocols TLSv1.2 TLSv1.3;
+ ssl_prefer_server_ciphers on;
+ ssl_session_cache shared:SSL:2m;
+ ssl_session_timeout 1h;
+ ssl_session_tickets off;
+ gzip_vary on;
+
+ log_format main '$remote_addr - $remote_user [$time_local] "$request" '
+ '$status $body_bytes_sent "$http_referer" '
+ '"$http_user_agent" "$http_x_forwarded_for"';
+
+ access_log /var/log/nginx/access.log main;
+
+ include /etc/nginx/http.d/*.conf;
+}
+
+
A => nginx/proxy.conf +5 -0
@@ 1,5 @@
+real_ip_header X-Forwarded-For;
+real_ip_recursive on;
+proxy_set_header Host $host;
+proxy_set_header X-Forwarded-Proto https;
+proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
A => nginx/uwsgi.conf +22 -0
@@ 1,22 @@
+real_ip_header X-Forwarded-For;
+real_ip_recursive on;
+proxy_set_header Host $host;
+proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+
+uwsgi_param QUERY_STRING $query_string;
+uwsgi_param REQUEST_METHOD $request_method;
+uwsgi_param CONTENT_TYPE $content_type;
+uwsgi_param CONTENT_LENGTH $content_length;
+
+uwsgi_param REQUEST_URI $request_uri;
+uwsgi_param PATH_INFO $document_uri;
+uwsgi_param DOCUMENT_ROOT $document_root;
+uwsgi_param SERVER_PROTOCOL $server_protocol;
+uwsgi_param REQUEST_SCHEME $scheme;
+uwsgi_param HTTPS $https if_not_empty;
+
+uwsgi_param REMOTE_ADDR $remote_addr;
+uwsgi_param REMOTE_PORT $remote_port;
+uwsgi_param SERVER_PORT $server_port;
+uwsgi_param SERVER_NAME $server_name;
+
A => nitter/Makefile +31 -0
@@ 1,31 @@
+CONMAN=sudo docker
+COLORIZE=| { GREP_COLORS="ms=01;32" grep -e '.*' --color=always || true; }
+
+REGISTRY=registry.intra.dominic-ricottone.com
+IMAGE=nitter
+TAG_AMD64=amd64
+TAG_ARM64=arm64
+
+image: image-amd64 image-arm64
+
+image-amd64:
+ cd src && $(CONMAN) buildx build --push \
+ --platform linux/amd64 \
+ --tag $(REGISTRY)/$(IMAGE):$(TAG_AMD64) \
+ .
+
+image-arm64:
+ cd src && $(CONMAN) buildx build --push \
+ --platform linux/arm64 \
+ --tag $(REGISTRY)/$(IMAGE):$(TAG_ARM64) \
+ . -f Dockerfile.arm64
+
+sync:
+ $(CONMAN) image push $(REGISTRY)/$(IMAGE):$(TAG_AMD64) $(COLORIZE)
+ $(CONMAN) image push $(REGISTRY)/$(IMAGE):$(TAG_ARM64) $(COLORIZE)
+
+clean:
+ $(CONMAN) image rm $(REGISTRY)/$(IMAGE):$(TAG_AMD64) $(COLORIZE)
+ $(CONMAN) image rm $(REGISTRY)/$(IMAGE):$(TAG_ARM64) $(COLORIZE)
+
+.PHONY: image sync clean
A => nitter/README.md +75 -0
@@ 1,75 @@
+# nitter
+
+
+## Build and Deploy
+
+```
+make image
+```
+
+
+### Tags
+
+ + `amd64`
+ + `arm64`
+
+----
+
+## Use
+
+Can be used with any container manager toolchain.
+
+Create a configuration file in `$conffile`. It should look like:
+
+```
+[Server]
+address = "0.0.0.0"
+port = 8080
+https = false
+httpMaxConnections = 10
+staticDir = "./public"
+title = "nitter"
+hostname = "nitter.example.com"
+
+[Cache]
+listMinutes = 240
+rssMinutes = 10
+redisHost = "redis"
+redisPort = 6379
+redisPassword = ""
+redisConnections = 20
+redisMaxConnections = 30
+
+[Config]
+hmacKey = "random key for cryptographic signing of video urls"
+base64Media = false
+enableRSS = false
+enableDebug = false
+proxy = ""
+proxyAuth = ""
+tokenCount = 10
+
+cookieHeader = "ct0=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; auth_token=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+xCsrfToken = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+
+[Preferences]
+theme = "Nitter"
+replaceTwitter = "nitter.example.com"
+replaceYouTube = ""
+replaceReddit = ""
+replaceInstagram = ""
+proxyVideos = true
+hlsPlayback = false
+infiniteScroll = false
+```
+
+Try:
+
+```
+$conman run --detach --name redis --restart always \
+ docker.io/library/redis:6-alpine redis-server
+$conman run --detach --name nitter --restart always \
+ --mount type=bind,src=$conffile,dst=/src/nitter.conf \
+ registry.intra.dominic-ricottone.com/nitter:latest
+```
+
A => nitter/src +1 -0
@@ 1,1 @@
+Subproject commit 892caaf7962f2a6df6addf37cf26db28fe73f7fd