2023-08-11 / @syui

flyio

fly.ioから自鯖に移行した

去年の8月までは$0で運用できてたんだけど、そこから約1年、月に$30~40くらいでした。$30は確実に超えてる感じなので、$40のほうが実態に近いかな。

つまり、この1年で$360~480くらいかかってる。

移行も面倒なのでしばらく放置してたんだけど、fly.ioでhostingしているmastodonが思うように動かなくなってきており、具体的には、激重になってた。

これはmastodonを動かすのに使っていたredisの裏技が封印された事によるものだと思う。

年に$360~480かけて激重のmastodonを運用するのは割に合わないと思ったので、移行を決意。fly.ioにhostしてたほぼすべてのサーバーを自前運用に切り替えました。

目標としては、また$0を目指す感じになりそう。

postgres backup & restore

fly.ioのpostgresのbackupとdockerへのrestoreの手順です。

$ brew install libpq
$ echo 'export PATH="/opt/homebrew/opt/libpq/bin:$PATH"' >> ~/.zshrc
$ source ~/.zshrc

$ flyctl proxy 5432 -a $pg_app_name
# postgres://${username}:${password}@${host}:5432/${db_name}
$ pg_dump -h localhost -p 5432 -U $username $db_name >! pg.dump
$ sudo docker compose up db
$ su
$ cat pg.dump | docker compose exec -T db psql -U $username -p 5432

これは、docker-composeの構成によります。例えば、下記の場合は、こうなります。

$ sudo docker compose up mitra_postgres
$ su
$ cat pg.dump | docker compose exec -T mitra_postgres psql -U postgres -p 5433
version: '3.9'
services:
  mitra:
    container_name: mitra
    build: .
    network_mode: host
    restart: unless-stopped
    volumes:
      - type: bind
        source: ./files
        target: /app/files
    env_file:
      - .env.local

  mitra_postgres:
    image: postgres:latest
    container_name: mitra_postgres
    ports:
      - 5433:5433
    volumes:
      - mitra_db:/var/lib/postgresql/data

    environment:
      - POSTGRES_PASSWORD=$password

volumes:
  mitra_db:

fly.io volume backup

$ fly ssh sftp shell r
$ get /path/to/dir ./
$ aunpack dir.zip

これを解凍してdockerのvolumeに設定するといいでしょう。

docker compose volume

docker composeのvolumemについても解説します。

    volumes:
      - mitra_db:/var/lib/postgresql/data

volumes:
  mitra_db:

これは、/var/lib/docker/volumesになります。

$ sudo ls /var/lib/docker/volumes

これをrepoに置きたい場合はこのようにします。

    volumes:
      - ./mitra_db:/var/lib/postgresql/data

これで./mitra_dbに保存されます。

docker volume owner

    build:
      context: .
      args:
        - UID
        - GID
        - USERNAME=user
        - GROUPNAME=user
ARG UID
ARG GID
ARG USERNAME
ARG GROUPNAME
RUN groupadd -g ${GID} ${GROUPNAME} -f && \
    useradd -m -s /bin/bash -u ${UID} -g ${GID} ${USERNAME}
$ sudo docker compose build --build-arg UID="$(id -u)" --build-arg GID="$(id -g)"

systemd

[Unit]
Description=mitra service
Documentation=https://codeberg.org/silverpill/mitra
Requires=docker.service
After=docker.service

[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/home/syui/flyio/mitra
ExecStart=/usr/bin/docker compose up -d
ExecStop=/usr/bin/docker compose down

[Install]
WantedBy=default.target
$ sudo systemctl daemon-reload
$ sudo systemctl start mitra
$ sudo systemctl enable mitra

mastodon

mastodonは127.0.0.10.0.0.0にしないとlocalhostにアクセスできなかった。また、service_namepg_portは他のコンテナとかぶるので変更。

https://github.com/mastodon/mastodon/blob/main/docker-compose.yml

DB_HOST=ms_db
DB_PORT=5434
REDIS_HOST=ms_redis
version: '3'
services:
  ms_db:
    restart: always
    image: postgres:14-alpine
    shm_size: 256mb
    ports:
      - 5434:5434
    networks:
      - internal_network
    healthcheck:
      test: ['CMD', 'pg_isready', '-U', 'postgres']
    volumes:
      - ./postgres14:/var/lib/postgresql/data
    environment:
      - POSTGRES_HOST_AUTH_METHOD=trust
      - POSTGRES_PASSWORD=$password
      - PGPORT=5434

  ms_redis:
    restart: always
    image: redis:7-alpine
    networks:
      - internal_network
    healthcheck:
      test: ['CMD', 'redis-cli', 'ping']
    volumes:
      - ./redis:/data

  mastodon:
    build: .
    image: ghcr.io/mastodon/mastodon:edge
    restart: always
    env_file: .env.production
    command: bash -c "rm -f /mastodon/tmp/pids/server.pid; bundle exec rails s -p 3000"
    networks:
      - external_network
      - internal_network
    healthcheck:
      # prettier-ignore
      test: ['CMD-SHELL', 'wget -q --spider --proxy=off localhost:3000/health || exit 1']
    ports:
      - '0.0.0.0:3000:3000'
    depends_on:
      - ms_db
      - ms_redis
      # - es
    volumes:
      - ./public/system:/mastodon/public/system

  streaming:
    build: .
    image: ghcr.io/mastodon/mastodon:edge
    restart: always
    env_file: .env.production
    command: node ./streaming
    networks:
      - external_network
      - internal_network
    healthcheck:
      # prettier-ignore
      test: ['CMD-SHELL', 'wget -q --spider --proxy=off localhost:4000/api/v1/streaming/health || exit 1']
    ports:
      - '0.0.0.0:4000:4000'
    depends_on:
      - ms_db
      - ms_redis

  sidekiq:
    build: .
    image: ghcr.io/mastodon/mastodon:edge
    restart: always
    env_file: .env.production
    command: bundle exec sidekiq
    depends_on:
      - ms_db
      - ms_redis
    networks:
      - external_network
      - internal_network
    volumes:
      - ./public/system:/mastodon/public/system
    healthcheck:
      test: ['CMD-SHELL', "ps aux | grep '[s]idekiq\ 6' || false"]

networks:
  external_network:
  internal_network:
    internal: true

matrix

install : https://matrix-org.github.io/dendrite/installation/docker/install

docker : https://github.com/matrix-org/dendrite/blob/main/build/docker/README.md

compose.yml : https://github.com/matrix-org/dendrite/blob/main/build/docker/docker-compose.yml

./configをdockerで作成し、dendrite.yml, keyをvolumeにすればいいです。

mkdir -p ./config
docker run --rm --entrypoint="/bin/sh" \
  -v $(pwd)/config:/mnt \
  matrixdotorg/dendrite-monolith:latest \
  -c "/usr/bin/generate-config \
    -dir /var/dendrite/ \
    -db postgres://dendrite:itsasecret@postgres/dendrite?sslmode=disable \
    -server YourDomainHere > ./config/dendrite.yaml"
version: "3.4"

services:
  matrix_postgres:
    hostname: matrix_postgres
    image: postgres:latest
    restart: always
    volumes:
      - dendrite_postgres_data:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: itsasecret
      POSTGRES_USER: dendrite
      POSTGRES_DATABASE: dendrite
      PGPORT: 5435
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U dendrite"]
      interval: 5s
      timeout: 5s
      retries: 5
    networks:
      - internal
    ports:
      - 5435:5435

  matrix:
    hostname: matrix
    image: matrixdotorg/dendrite-monolith:latest
    ports:
      - 8008:8008
      - 8448:8448
    volumes:
      - ./config:/etc/dendrite
      - ./data:/data
    depends_on:
      matrix_postgres:
        condition: service_healthy
    networks:
      - internal
    restart: unless-stopped

networks:
  internal:
    attachable: true

volumes:
  dendrite_postgres_data:

matrixは厄介で8448:8448.well-know/matrix/serverへの対応がわからなかった。これはcloudflareの設定になるんだけど、いけると思った設定ではmatrixが動かない感じだった。これはおそらく、tunnelで作られるdnsがproxy onになるためだと思う。

[[services]]
  internal_port = 8008
  protocol = "tcp"

  [[services.ports]]
    handlers = ["tls", "http"]
    port = "443"

  [[services.ports]]
    handlers = ["tls", "http"]
    port = "8448"

https://matrix-org.github.io/synapse/v1.41/delegate.html

{
    "m.server": "synapse.example.com:443"
}
$ sudo docker exec -it dendrite-matrix-1 /usr/bin/create-account -config /etc/dendrite/dendrite.yaml -username $USER -password $password -admin