"Bugs, Mr. Rico. Zillions of em!" Hughes, p. 248; reporting on a bug…

Written by Simone

"Bugs, Mr. Rico. Zillions of em!"

  • Hughes, p. 248; reporting on a bug assault to LT Juan Rico on Planet P.

Wikiquote

self-hosting di ente (photos)

Written by Simone

L'applicazione "photos" della società "ente" è una alternativa alla più rinomata Google Foto, ossia un'app che conserva le vostre immagini (anche chiamate "memories", ricordi) sul cloud. A seconda del profilo scelto potrete immagazzinare tot dati a determinati prezzi - a dire il vero esiste anche un piano di prova per un anno con 1GB di spazio, che naturalmente non soddisferà nessuno.

Da qualche settimana però ente ha deciso di rilasciare come codice aperto la sua versione del server, che può essere liberamente fatto girare sulla propria macchina insieme alle relative app (photos per Android, web app), tramite alcune modifiche alle stesse.

Io e lorenzo (@lorenzo@fedi.bobadin.icu) ci siamo allora messi in gioco per avere delle istanze personali di ente server ed uno spazio in cloud dove poter caricare il materiale (l'Object Storage S3 che abbiamo utilizzato è totalmente sponsorizzato da lorenzo, il quale ringrazio)

Sin da subito abbiamo avuto diverse difficoltà, perché la documentazione, ahimè, è divisa tra blog e repository github, con molte incosistenze e diverse lacune. Al momento però siamo riusciti ad avere un servizio funzionante con l'app photos; per la parte web invece ci sono ancora alcuni problemi.

In questo post riassumerò le operazioni effettuate.

Lo stack docker per i servizi ente è costituito da:

  • server (museum)
  • database pgsql
  • minio (object storage locale)
  • socat

Per utilizzare un S3 locale alla vostra macchina avete bisogno di tutti questi componenti, mentre utilizzando uno storage S3 esterno, basteranno solamente il server museum ed un database (docker o di sistema) Nella seguente guida parlerò solo di un sistema Debian con database installato localmente (quindi niente immagine docker) e S3 esterno (quindi niente minio/socat)

La guida di riferimento seguita è questa: https://github.com/ente-io/ente/blob/main/server/docs/docker.md e di seguito elencherò solo le modifiche apportate.

Utilizzeremo solo 3 file: compose.yaml e museum.yaml che andranno creati nella directory "ente", come da guida linkata sopra, mentre il percorso per credentials.yaml sarà scripts/compose/credentials.yaml, sempre all'interno della dir base "ente".

compose.yaml

Il file compose.yaml sarà il seguente:

services:
  museum:
    image: ghcr.io/ente-io/server
    restart: always
    network_mode: "host"
    environment:
      # Pass-in the config to connect to the DB and MinIO
      ENTE_CREDENTIALS_FILE: /credentials.yaml
    volumes:
      - custom-logs:/var/logs
      - ./museum.yaml:/museum.yaml:ro
      - ./scripts/compose/credentials.yaml:/credentials.yaml:ro
      - ./data:/data:ro

volumes:
  custom-logs:

Il network è stato cambiato da "internal" ad "host" per permettere al server ente nel contenitore docker di dialogare col database in localhost sul sistema operativo. La porta esposta sul sistema operativo non può essere modificata con network=host (se avviate il container con qualsiasi porta specificata otterrete un warning - Published ports are discarded when using host network mode), quindi è stata rimossa dal compose. Assicuratevi che la "8080" non sia già in uso da altri applicativi:

sudo netstat -lnp | grep 8080

museum.yaml

Il file museum.yaml, ridotto all'essenziale (più commenti), sarà il seguente:

# Configuring museum
# ------------------
#
#
# By default, museum logs to stdout when running locally. Specify this path to
# get it to log to a file instead.
#
# It must be specified if running in a non-local environment.
log-file: ""

# HTTP connection parameters
http:
    # If true, bind to 443 and use TLS.
    # By default, this is false, and museum will bind to 8080 without TLS.
    # use-tls: true

# Key used for encrypting customer emails before storing them in DB
#
# To make it easy to get started, some randomly generated values are provided
# here. But if you're really going to be using museum, please generate new keys.
# You can use `go run tools/gen-random-keys/main.go` for that.
key:
    encryption: <chiave>
    hash: <chiave>
    
# JWT secrets
#
# To make it easy to get started, a randomly generated values is provided here.
# But if you're really going to be using museum, please generate new keys. You
# can use `go run tools/gen-random-keys/main.go` for that.
jwt:
    secret: <chiave>

# SMTP configuration (optional)
#
# Configure credentials here for sending mails from museum (e.g. OTP emails).
#
# The smtp credentials will be used if the host is specified. Otherwise it will
# try to use the transmail credentials. Ideally, one of smtp or transmail should
# be configured for a production instance.
smtp:
    host:
    port:
    username:
    password:

# Various low-level configuration options
internal:
    # If false (the default), then museum will notify the external world of
    # various events. E.g, email users about their storage being full, send
    # alerts to Discord, etc.
    #
    # It can be set to true when running a "read only" instance like a backup
    # restoration test, where we want to be able to access data but otherwise
    # minimize external side effects.
    silent: false
    # If provided, this external healthcheck url is periodically pinged.
    health-check-url:
    # Hardcoded verification codes, useful for logging in when developing.
    #
    # Uncomment this and set these to your email ID or domain so that you don't
    # need to peek into the server logs for obtaining the OTP when trying to log
    # into an instance you're developing on.
    #hardcoded-ott:
    #     emails:
    #         - "example@example.org,123456"
    #     # When running in a local environment, hardcode the verification code to
    #     # 123456 for email addresses ending with @example.org
    #     local-domain-suffix: "@example.org"
    #     local-domain-value: 123456
    # List of user IDs that can use the admin API endpoints.
    admins: []

# Replication config
#
# If enabled, replicate each file to 2 other data centers after it gets
# successfully uploaded to the primary hot storage.
replication:
    enabled: false
    # The Cloudflare worker to use to download files from the primary hot
    # bucket. Must be specified if replication is enabled.
    worker-url:
    # Number of go routines to spawn for replication
    # This is not related to the worker-url above.
    # Optional, default value is indicated here.
    worker-count: 6
    # Where to store temporary objects during replication v3
    # Optional, default value is indicated here.
    tmp-storage: tmp/replication

# Configuration for various background / cron jobs.
jobs:
    cron:
        # Instances run various cleanup, sending emails and other cron jobs. Use
        # this flag to disable all these cron jobs.
        skip: false
    remove-unreported-objects:
        # Number of go routines to spawn for object cleanup
        # Optional, default value is indicated here.
        worker-count: 1
    clear-orphan-objects:
        # By default, this job is disabled.
        enabled: false
        # If provided, only objects that begin with this prefix are pruned.
        prefix: ""
        
stripe:
    path:
        success: ?status=success&session_id={CHECKOUT_SESSION_ID}
        cancel: ?status=fail&reason=canceled

Come (quasi) scritto nel commento, per generare chiavi e segreto jwt bisognerà clonare in una directory a piacere il server ente, entrare nella directory "server" e semplicemente digitare il comando:

go run tools/gen-random-keys/main.go

La configurazione di queste chiavi, come pure tutta la sezione SMTP è opzionale; se decidete di compilare i campi per smtp, la vostra istanza sarà di fatto aperta alle registrazioni utente, cosa che probabilmente non vorrete fare.

Se decidete di continuare, avrete bisogno di installare "go" in Debian; oppure se siete in fase di test utilizzate le chiavi di default presenti nel file: https://github.com/ente-io/ente/blob/main/server/configurations/local.yaml#L151-L161

sudo apt install golang-1.19-go

Altra dipendenza prima di eseguire il comando è: libsodium

sudo apt install libsodium23:amd64 libsodium-dev:amd64

credentials.yaml

Ultimo file di configurazione è credentials.yaml

db:
    host: localhost
    port: 5432
    name: ente_db
    user: ente
    password: password
    
s3:
    are_local_buckets: false
    use_path_style_urls: true
    b2-eu-cen:
        key: <key>
        secret: <secret>
        endpoint: link_allo_storage
        region: eu-central-2
        bucket: <bucket_name>

Questo file si compone dei dati del database postgres e dello storage esterno S3: la modifica essenziale per il databse è "host", che andrà impostato su "localhost"; per S3 è importante cambiare solamente "key", "secret", "endpoint" e "bucket"; lasciate gli altri valori intatti o avrete problemi di connessione; da quello che ho capito sono hard-coded.

E' giunta l'ora di creare il database:

sudo su - postgres

psql

CREATE DATABASE ente_db;
CREATE USER ente WITH PASSWORD 'sekret';
GRANT ALL PRIVILEGES ON DATABASE ente_db TO ente;

Modificate i nome di db, user e password a piacere (basta che siano uguali a quelli specificati in crednetials.yaml). Battete "enter" ad ogni riga. Postgres risponderà ad ogni comando con una conferma circa le operazioni eseguite.

Per uscire dalla cli di pg:

\quit

Per tornare al vostro utente:

exit

E lanciamo docker:

sudo docker compose up

Controllate i log, l'importante è che il database sia correttamente connesso; comparirà qualche errore in seguito, ma se il server rimane in esecuzione senza fermarsi dovrebbe essere tutto a posto.

Il server rimane in ascolto su localhost, porta 8080. Per poter raggiungerlo dall'esterno bisognerà configurare un reverse proxy nel vostro web server - Apache, nginx o caddy.

Lascio qui una configurazione di esempio per nginx:

map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
}
server {
    server_name sottodominio.dominio.tld;

    access_log /var/log/nginx/sottodominio/access.log;
    error_log /var/log/nginx/sottodominio/error.log;

    location / {
           proxy_pass http://[::1]:8080;
           proxy_set_header Host $host;
           proxy_set_header X-Real-IP $remote_addr;
           proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
           proxy_set_header X-Forwarded-Proto $scheme;
    }

    listen [::]:443 ssl http2;
    listen 443 ssl http2;
    ssl_certificate /etc/letsencrypt/live/sottodominio.dominio.tld/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/sottodominio.dominio.tld/privkey.pem;
}

La mia configurazione prevede supporto a IPv6; in caso voleste usare solamente IPv4, cambiate l'host in proxy_pass e togliete il listen [::]:443 ssl http2;

Ora, scaricate l'app ente photos dal loro repository github, poiché quella sul Play Store non è stata ancora aggiornata coi cambiamenti necessari al funzionamento su server self-hosted.

Avviata l'app sul telefono, tappate 7 o più volte in rapida successione sulla schermata di avvio finché non apparirà un campo di testo: riempitelo con l'indirizzo che avete configurato per il reverse proxy:

https://sottodominio.dominio.tld

Connettete e dovreste vedere un messaggio di conferma se tutto è andato bene, con sotto scritto l'indirizzo a cui siete collegati.

Una volta nell'app dovrete registrare un account. Inserite email e password ed alla schermata successiva vi verrà chiesto un codice OTP di conferma. L'app vi dirà che il codice è stato inviato alla vostra casella email, ma questo è vero solo nel caso abbiate impostato i campi per SMTP, come spiegato sopra (altra cosa da sapere è che il mittente delle email è ente <verification@ente.io>, quindi non vi spaventate). In caso contrario il codice OTP può essere recuperato facilmente dai log docker che staranno scorrendo nel terminale. verrà scritto qualcosa come "OTT per id sfilza di caratteri: e qui un codice di 6 cifre". Ricopiatelo nell'app e proseguite.

Dopo alcuni istanti per il setup della crittografia arriverà una schermata con una passphrase che dovrete conservare in luogo sicuro, per il ripristino dell'account in caso di perdita della password di accesso.

Scegliete ora le cartelle sul vostro telefono di cui fare backup e cominciate!

Se lo storage è connesso correttamente vedrete i vostri ricordi in caricamento con un numero progressivo; in caso contario, se qualcosa non sta funzionando, sulle vostre foto rimarrà una nuvoletta barrata, che indica il mancato caricamento. Se questo fosse il caso, andate di nuovo a leggere i log del container per eventuali errori.

Sbloccare il limite di 1GB su profilo di prova

Nonostante stiamo usando un server personale, noterete che l'app photos mostra ancora i profili/sottoscrizioni a pagamento dell'app originale.

Per poter sbloccare lo storage pressoché infinito, dopo aver selezionato il profilo di prova ad 1GB, bisognerà utilizzare uno strumento a riga di comando - ente cli.

E' necessario installare alcuni pacchetti, generalmente utilizzati in versione Linux Desktop e lanciare alcuni comandi per attivare la "secret service dbus interface", necessaria alla cli ente.

sudo apt install gnome-keyring libsecret dbus-x11

Eseguite questi comandi, copio incollo perché è inutile soffermarsi oltre:

eval "$(dbus-launch --sh-syntax)"

mkdir -p ~/.cache
mkdir -p ~/.local/share/keyrings # where the automatic keyring is created

# 1. Create the keyring manually with a dummy password in stdin
eval "$(printf '\n' | gnome-keyring-daemon --unlock)"

# 2. Start the daemon, using the password to unlock the just-created keyring:
eval "$(printf '\n' | /usr/bin/gnome-keyring-daemon --start)"

A questo punto l'ambiente è pronto. Scaricate ente cli dal repository github: https://github.com/ente-io/ente/releases/tag/cli-v0.1.13

Nel nostro caso, per Debian x64, scaricheremo: https://github.com/ente-io/ente/releases/download/cli-v0.1.13/ente-cli-v0.1.13-linux-amd64.tar.gz

Estraete il contenuto della "tarpalla" in una directory a piacere, magari in ~/bin Dentro alla stessa directory, create un file chiamato config.yaml, contenente le seguenti righe:

endpoint:
    api: "http://localhost:8080"

Dalla stessa directory, lanciamo ./ente help per verificarne il corretto funzionamento e.. leggere l'help 😀

Per prima cosa aggiungiamo il nostro utente creato precedentemente:

./ente account add

Vi verrano chieste alcune info, in particolare indirizzo email con cui vi siete registrati su photos, relativa password e una dir dove poter esportare le vostre immagini (la dir deve esistere prima di poterla specificare).

Una volta aggiunto l'account, digitate:

./ente account list

E dovreste vedere le info del vostro account, tra le quali un "ID". Copiatelo ed aprite nuovamente il file "museum.yaml" visto in precedenza. In questa sezione modificate la voce "admins" inserendo tra le parentesi quadre l'ID utente copiato. Salvate e riavviate il contenitore docker; da questo momento siete admin dell'istanza.

internal:
    # If false (the default), then museum will notify the external world of
    # various events. E.g, email users about their storage being full, send
    # alerts to Discord, etc.
    #
    # It can be set to true when running a "read only" instance like a backup
    # restoration test, where we want to be able to access data but otherwise
    # minimize external side effects.
    silent: false
    # If provided, this external healthcheck url is periodically pinged.
    health-check-url:
    # Hardcoded verification codes, useful for logging in when developing.
    #
    # Uncomment this and set these to your email ID or domain so that you don't
    # need to peek into the server logs for obtaining the OTP when trying to log
    # into an instance you're developing on.
    #hardcoded-ott:
    #     emails:
    #         - "example@example.org,123456"
    #     # When running in a local environment, hardcode the verification code to
    #     # 123456 for email addresses ending with @example.org
    #     local-domain-suffix: "@example.org"
    #     local-domain-value: 123456
    # List of user IDs that can use the admin API endpoints.
    admins: []

Torniamo alla cli:

./ente admin list-users

Dovreste vedere voi stessi e leggere che siete effettivamente admin.

Ultimo comando per sbloccare lo storage da 100TB e abbiamo finito:

./ente admin update-subscription -u email@vostrodominio.tld --no-limit true

The Internet doesn't like VPNs

Written by Simone

It's been a week or so that I started using Wireguard on my desktop too, browsing the Internet and doing the usual stuff I do, but this time connecting both via IPv4 and IPv6 through my VPS.

Results? I've already been banned (or to better state it, my VPS's IPv4 has) from 3 popular hosts: reddit, imgur and alienwarearena. Reason? I don't really know, looks like everyone doesn't like VPNs.

For the time being I resorted to replace reddit.com with old.reddit.com (even in my SearxNG instance) to be able to browse that shit, which unfortunately is sometimes useful. "imgur" is even more trickier, since I was still able to upload images (and also display them) via their API on Glowing-Bear.. But if I try to curl imgur.com from my VPS shell I get this:

{"data":{"error":"Imgur is temporarily over capacity. Please try again later."},"success":false,"status":403}

"Over capacity", yeah, but it's a 403, you liar!

So, a few moments ago I set my Wireguard service in Windows to manual start, stopped it and now I'm back with Hurricane Electric IPv6 tunnel - I would like to avoid being banned from the rest of the world, if possible.

Thanks for all the fish.

Young me doing IT stuff

Written by Simone

written notes about msdos

Obsolete major version 13 (uh oh!)

Written by Simone

A package configuration text screen by Debian apt which is informing the user that postgresql packages are old and need to be upgraded.

Yesterday after installing some new packages I was greeted by this kind reminder 😀

I began stopping services which use a Postgresql database and even forgot about Dendrite.. Nothing so bad as I imagined, tho, just run the suggested commands and everything got up and running in a few minutes.

Debian rocks! 😍

Notes

Written by Simone

I'll update this post whenever I see fits, A.K.A. when I have other bits of information which don't require a whole post.

Operations on files and directories

Move files and directories to the current/parent directory in Linux

Current dir

find . -type f -exec mv {} . \;

Parent dir

find . -type f -exec mv {} .. \;

Recursive chmod on files and dirs

To change all the directories to 755 (-rwxr-xr-x):

find /var/www/blog -type d -exec chmod 755 {} \;

To change all the files to 644 (-rw-r--r--):

find /var/www/blog -type f -exec chmod 644 {} \;

Certbot common commands

Register single domain:

certbot certonly --standalone -d domain.tld --dry-run

Renew single domain:

certbot renew --cert-name domain.tld --dry-run
  • Remove “–dry-run” when ok.

Revoke certificate:

certbot revoke --cert-path /etc/letsencrypt/archive/${YOUR_DOMAIN}/cert1.pem

Check certificate's expiry date:

cat /etc/letsencrypt/live/domain.tld/cert.pem | openssl x509 -noout -enddate

GIT

To reset your git repository to given commit id, do:

git reset --hard <commit-id>
git push origin master --force

Ignoring files that are already tracked

git update-index --assume-unchanged <your file here>

Delta Chat Mail sieve

require ["fileinto"];
# rule:[DeltaChat]
if header :contains "Chat-Version" "1.0"
{
	fileinto "DeltaChat";
	stop;
}

Postfix mail queue

To view postfix mail queue in case of problems and remove a particular message from it, do as follows:

# mailq

-Queue ID-  --Size-- ----Arrival Time---- -Sender/Recipient-------
6DCF32201B*    4824 Thu Oct 19 22:54:44  roughnecks@woodpeckersnest.eu
                                         debian@spacenet.it

-- 4 Kbytes in 1 Request.
# postsuper -d 6DCF32201B

postsuper: 6DCF32201B: removed
postsuper: Deleted: 1 message

Check Preferred Outgoing IP (when multiple are set on <interface>)

curl ifconfig.me

The correct command to add a new Linux user (in this case without a shell)

adduser --shell /usr/sbin/nologin <username>

I always forget which command is the complete one, useradd or adduser

Wireguard IPv6

Written by Simone

Here's my configuration, working fine with my Android 9 Phone

server.conf

root@pandora:~# cat /etc/wireguard/wg0.conf
[Interface]
# specify generated private key for server
PrivateKey = <sekret>
# IP address for VPN interface
Address = 172.16.100.1/32, fd42:42:42::1/64
MTU = 1420
# UDP port WireGuard server listens
ListenPort = 51820

# possible to set any commands after WireGuard starts/stops
# set routing rules like follows to access to local network via VPN session
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE; ip6tables -A FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE; ip6tables -D FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -D POSTROUTING -o eth0 -j MASQUERADE;

[Peer]
# REDMI
# specify public key for client
PublicKey = <sekret>
# clients' VPN IP addresses you allow to connect
# possible to specify subnet ⇒ [172.16.100.0/24]
AllowedIPs = 172.16.100.6/32, fd42:42:42::6/128
PersistentKeepalive = 25

client.conf

root@pandora:~# cat /etc/wireguard/redmi.conf
[Interface]
#Private IP Address
Address = fd42:42:42::6/128, 172.16.100.6/32
#Client's Private Key
PrivateKey = <sekret>
#Server's listening port
ListenPort = 51820

[Peer]
#Server's Public Key
PublicKey = <sekret>
AllowedIPs = ::0/0, 0.0.0.0/0
#Server's IP:port
Endpoint = woodpeckersnest.space:51820

sysctl.conf

root@pandora:~# sysctl -p
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
net.ipv6.conf.eth0.accept_ra = 2

Trilium Notes

Written by Simone

A screenshot of the web app

I'm super impressed by Trilium Notes, a wonderful note-taking app and self-hostable service.

Used docker to host it and web to manage my notes. It saves instantly, no button to press, has a lot of useful functions, it's scriptable, does backups automatically and it offers extensions for chrome and firefox.

Two issue though:

  • chrome extension will become unsupported later on in 2024, because it uses manifest v2
  • developers just posted a couple days ago about putting the project into maintenance mode :(

Although this is kinda sad, I have used the app for the past 2 days and it works very well, so much that I finally ditched MS One Note (yes I use Windows on my Desktop - shame! shame! shame!)

XMPP Network Graph

Written by Simone

Setting up IPv6 in Windows

Written by Simone

Found this post quite useful to set up Hurricane Electric's IPv6 on a Windows machine and serve the connection over LAN (Windows machine must stay on, obviously)

Legend of variables:
$ipv4a   = tunnel server's IPv4 IP
$ipv4b   = user's IPv4 IP
$ipv6a   = tunnel server's side of point-to-point /64 allocation
$ipv6b   = user's side of point-to-point /64 allocation
$ipv6c   = first address of user's routed /64 allocation
$ipv6d   = user's routed /64 allocation
$adapter = name of local area network connection (where your IPv4 address is configured now)

netsh int teredo set state disabled
netsh int ipv6 add v6v4tunnel IP6Tunnel $ipv4b $ipv4a
netsh int ipv6 add address IP6Tunnel $ipv6b

netsh int ipv6 set interface IP6Tunnel forwarding=enabled
netsh int ipv6 set interface "$adapter" forwarding=enabled advertise=enabled
netsh int ipv6 add address "$adapter" $ipv6c
netsh int ipv6 set route $ipv6d "$adapter" publish=yes
netsh int ipv6 add route ::/0 IP6Tunnel $ipv6c publish=yes