마스토돈 서버 설정 기록

마스토돈 서버 설정 기록

홈 서버에 Mastodon 인스턴스를 직접 설치한 기록을 남깁니다.

참고 문서 안내

이 문서는 Mastodon 인스턴스를 설치한 기록을 잊지 않기 위해 남긴 것입니다. 대부분의 명령어 및 설정은 다음 문서에 있는 그대로 따랐으며, 도커 이미지 버전 등 사소한 수정만이 있었습니다. 따라서 대부분의 내용이 다음 문서와 크게 다르지 않습니다. 자세한 내용이 필요하신 경우 다음 문서를 참조해주세요.

How to take advantage of Docker to install Mastodon – sleeplessbeastie’s notes
Take advantage of Docker to install Mastodon This article is based on the official docker compose which can be found the in mastodon project repository. Operating system. $ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 22.04 LTS Release: 22.04 Codename: jamm…

웹 주소와 로컬 주소를 나누는 부분은 공식 문서의 다음 설명을 참조하였습니다.

Configuring your environment
Setting environment variables for your Mastodon installation.

준비사항

서버

항상 켜둘 수 있는 서버를 준비합니다. 저는 데비안 홈 서버를 활용했습니다.

도메인 주소

도메인 주소를 준비하여 서버의 IP 주소를 가리키도록 설정합니다. 유동 IP를 사용하는 서버의 경우 DDNS(동적 DNS) 기능을 지원하는 서비스를 활용해 서버를 가리키도록 설정합니다.

(선택사항) 웹 주소와 로컬 주소를 다르게 설정 가능합니다. 예를 들어, mastodon.example.com을 웹 주소로 사용하면서 example.com을 로컬 주소로 사용하면 상대적으로 짧은 example.com 도메인을 다른 용도로 사용하면서 사용자 핸들로도 사용하여 외우기 쉽도록 만들 수 있습니다. 이렇게 사용하려면 두 도메인이 모두 서버를 가리키도록 해야 합니다. 이와 관련된 설정은 아래에서 소개합니다.

설치 과정

의존성 설치

서버에 다음 의존성들을 설치합니다. 대부분 Mastodon 설치 시 PostgreSQL을 Docker로 실행하는 것을 권장하고 있지만, 저는 PostgreSQL은 하나의 인스턴스를 설치하여 관리하는 것을 선호하여 직접 설치한 상태입니다. 이 문서는 그러한 환경을 가정하여 작성되었음을 알립니다. 만약 Docker로 PostgreSQL을 관리하기 원하시는 경우 처음 언급한 문서의 내용을 따라주세요.

  • nginx 설치 – 문서 보기
  • certbot 설치 – 문서 보기
    • 사용할 도메인의 인증서를 발급받으세요. 추후 자동 연장 등 관리를 편리하게 하기 위해 nginx 설정 방식으로 발급받으시는 것을 추천드립니다.
    • (선택사항) 웹 주소와 로컬 주소를 다르게 설정할 경우 두 도메인 모두의 인증서가 필요합니다.
  • postgresql 설치 – 문서 보기
  • docker 설치 – 문서 보기
  • docker-compose 설치 – 문서 보기

PostgreSQL 설정

계정 및 데이터베이스 생성

Mastodon 인스턴스에서 사용할 계정 및 데이터베이스를 생성합니다. 이 곳에서 설정한 계정의 암호는 아래 설정에서 사용됩니다.

$ createuser mastodon -d -P
새 롤의 암호:
암호 확인:
$ createdb -U mastodon -h localhost mastodon_production
암호:

접근 권한 설정

Docker 컨테이너에서 계정 및 데이터베이스에 접근할 수 있도록 설정합니다.

$ echo "host mastodon_production mastodon 172.0.0.0/8 md5" | sudo tee -a /etc/postgresql/14/main/pg_hba.conf
$ echo "host mastodon_production mastodon 192.168.0.0/16 md5" | sudo tee -a /etc/postgresql/14/main/pg_hba.conf

PostgreSQL에서 localhost가 아닌 주소에서도 접근할 수 있도록 설정합니다.

$ sudo vim /etc/postgresql/14/main/postgresql.conf

listen_addresses 항목을 찾아 값을 *으로 바꿔줍니다.

#------------------------------------------------------------------------------
# CONNECTIONS AND AUTHENTICATION
#------------------------------------------------------------------------------

# - Connection Settings -

listen_addresses = '*'                  # what IP address(es) to listen on;
                                        # comma-separated list of addresses;
                                        # defaults to 'localhost'; use '*' for all
                                        # (change requires restart)

데이터베이스 재시작

$ sudo service postgresql restart

Elasticsearch 설정

Elasticsearch의 원활한 실행을 위해 max_map_count 값을 조정합니다.

$ sudo sysctl vm.max_map_count
vm.max_map_count = 65530
$ echo "vm.max_map_count=262144" | sudo tee /etc/sysctl.d/90-max_map_count.conf
$ sudo sysctl --system

디렉터리 생성

서버 운영에 필요한 디렉터리를 생성하고 권한을 설정합니다.

$ sudo mkdir /opt/mastodon/
$ sudo mkdir -p /opt/mastodon/database/{redis,elasticsearch}
$ sudo chown 1000 /opt/mastodon/database/elasticsearch
$ sudo mkdir -p /opt/mastodon/web/system
$ sudo chown 991:991 /opt/mastodon/web/system

Docker Compose 파일 생성

다음과 같이 docker-compose.yml 파일을 생성합니다.

$ cat << EOF | sudo tee /opt/mastodon/docker-compose.yml
version: '3'

services:

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

  redis-volatile:
    image: redis:7.0.5-alpine
    restart: always
    healthcheck:
      test: ['CMD', 'redis-cli', 'ping']
    networks:
      - internal_network

  elasticsearch:
    image: elasticsearch:7.17.7
    restart: always
    env_file: database.env
    environment:
      - cluster.name=elasticsearch-mastodon
      - discovery.type=single-node
      - bootstrap.memory_lock=true
      - xpack.security.enabled=true
      - ingest.geoip.downloader.enabled=false
    ulimits:
      memlock:
        soft: -1
        hard: -1
    healthcheck:
      test: ["CMD-SHELL", "nc -z elasticsearch 9200"]
    volumes:
      - elasticsearch:/usr/share/elasticsearch/data
    networks:
      - internal_network

  website:
    image: tootsuite/mastodon:v4.1.4
    env_file:
      - application.env
      - database.env
    command: bash -c "bundle exec rails s -p 3000"
    restart: always
    depends_on:
      - redis
      - redis-volatile
      - elasticsearch
    ports:
      - '127.0.0.1:3000:3000'
    networks:
      - internal_network
      - external_network
    extra_hosts:
      - "host.docker.internal:host-gateway"
    healthcheck:
      test: ['CMD-SHELL', 'wget -q --spider --proxy=off localhost:3000/health || exit 1']
    volumes:
      - uploads:/mastodon/public/system

  shell:
    image: tootsuite/mastodon:v4.1.4
    env_file:
      - application.env
      - database.env
    command: /bin/bash
    restart: "no"
    networks:
      - internal_network
      - external_network
    extra_hosts:
      - "host.docker.internal:host-gateway"
    volumes:
      - uploads:/mastodon/public/system

  streaming:
    image: tootsuite/mastodon:v4.1.4
    env_file:
      - application.env
      - database.env
    command: node ./streaming
    restart: always
    depends_on:
      - redis
      - redis-volatile
      - elasticsearch
    ports:
      - '127.0.0.1:4000:4000'
    networks:
      - internal_network
      - external_network
    extra_hosts:
      - "host.docker.internal:host-gateway"
    healthcheck:
      test: ['CMD-SHELL', 'wget -q --spider --proxy=off localhost:4000/api/v1/streaming/health || exit 1']

  sidekiq:
    image: tootsuite/mastodon:v4.1.4
    env_file:
      - application.env
      - database.env
    command: bundle exec sidekiq
    restart: always
    depends_on:
      - redis
      - redis-volatile
      - website
    networks:
      - internal_network
      - external_network
    extra_hosts:
      - "host.docker.internal:host-gateway"
    healthcheck:
      test: ['CMD-SHELL', "ps aux | grep '[s]idekiq\ 6' || false"]
    volumes:
      - uploads:/mastodon/public/system

networks:
  external_network:
  internal_network:
    internal: true

volumes:
  redis:
    driver_opts:
      type: none
      device: /opt/mastodon/database/redis
      o: bind
  elasticsearch:
    driver_opts:
      type: none
      device: /opt/mastodon/database/elasticsearch
      o: bind
  uploads:
    driver_opts:
      type: none
      device: /opt/mastodon/web/system
      o: bind
EOF

설정 과정

⚠️
주의!
아래 생성된 값은 예시입니다. 명령어를 직접 실행하여 값을 생성해 사용해주세요. 또한 생성된 값은 외부에 노출되지 않도록 관리해주세요.

필요한 값 생성

설정 파일 생성에 필요한 값들을 생성합니다.

$ sudo touch /opt/mastodon/application.env
$ sudo touch /opt/mastodon/database.env
$ openssl rand -hex 16
f427655f781fb510...(생략됨)
$ sudo docker-compose -f /opt/mastodon/docker-compose.yml run --rm shell bundle exec rake secret
Creating network "mastodon_internal_network" with the default driver
Creating network "mastodon_external_network" with the default driver
Creating volume "mastodon_redis" with default driver
Creating volume "mastodon_elasticsearch" with default driver
Creating volume "mastodon_uploads" with default driver
0701fa876663c4e4...(생략됨)
$ sudo docker-compose -f /opt/mastodon/docker-compose.yml run --rm shell bundle exec rake secret
0309a599e8ef767d...(생략됨)
$ sudo docker-compose -f /opt/mastodon/docker-compose.yml run --rm shell bundle exec rake mastodon:webpush:generate_vapid_key
VAPID_PRIVATE_KEY=kKz6fGDFsSEV-q3I...(생략됨)
VAPID_PUBLIC_KEY=BMf1qY_YSybedtBs...(생략됨)

위 실행 결과에서 나온 다음 값들을 아래 과정에서 다음과 같이 사용합니다.

  • ELASTIC_PASSWORD, ES_PASS: f427655f781fb510...(생략됨)
  • SECRET_KEY_BASE: 0701fa876663c4e4...(생략됨)
  • OTP_SECRET: 0309a599e8ef767d...(생략됨)
  • VAPID_PRIVATE_KEY: kKz6fGDFsSEV-q3I...(생략됨)
  • VAPID_PUBLIC_KEY: BMf1qY_YSybedtBs...(생략됨)

데이터베이스 설정 파일 생성

위에서 만들어진 값들을 활용해 database.env 설정 파일을 생성합니다.

$ cat << EOF | sudo tee /opt/mastodon/database.env
# elasticsearch
ES_JAVA_OPTS=-Xms512m -Xmx512m
ELASTIC_PASSWORD=f427655f781fb510...(생략됨)

# mastodon database configuration
DB_HOST=host.docker.internal
DB_USER=mastodon
DB_NAME=mastodon_production
DB_PASS=(위에서 설정한 데이터베이스 계정의 암호)
DB_PORT=5432

REDIS_HOST=redis
REDIS_PORT=6379

CACHE_REDIS_HOST=redis-volatile
CACHE_REDIS_PORT=6379

ES_ENABLED=true
ES_HOST=elasticsearch
ES_PORT=9200
ES_USER=elastic
ES_PASS=f427655f781fb510...(생략됨)
EOF

Mastodon 인스턴스 설정 파일 생성

위에서 만들어진 값들을 활용해 application.env 설정 파일을 생성합니다. mastodon.example.com으로 적혀 있는 도메인은 사용하시려는 도메인으로 교체해주세요.

(선택사항) 여기에서 웹 주소와 로컬 주소를 다르게 설정할 수 있습니다. 만약 웹 주소를 mastodon.example.com으로 그리고 로컬 주소를 example.com으로 설정하고 싶으시다면, WEB_DOMAIN 값의 주석을 해제하여 mastodon.example.com으로 그리고 LOCAL_DOMAIN 값을 example.com으로 설정하시면 됩니다. 이 결정은 되돌릴 수 없으므로 잘 생각하시고 결정하시기 바랍니다.

$ cat << EOF | sudo tee /opt/mastodon/application.env
# environment
RAILS_ENV=production
NODE_ENV=production

# domain
#WEB_DOMAIN=
LOCAL_DOMAIN=mastodon.example.com

# redirect to the first profile
SINGLE_USER_MODE=true

# serve static files
RAILS_SERVE_STATIC_FILES=true

# concurrency
WEB_CONCURRENCY=2
MAX_THREADS=5

# locale
DEFAULT_LOCALE=ko

# email, not used
SMTP_SERVER=localhost
SMTP_PORT=587
SMTP_FROM_ADDRESS=notifications@mastodon.example.com

# secrets
SECRET_KEY_BASE=0701fa876663c4e4...(생략됨)
OTP_SECRET=0309a599e8ef767d...(생략됨)

VAPID_PRIVATE_KEY=kKz6fGDFsSEV-q3I...(생략됨)
VAPID_PUBLIC_KEY=BMf1qY_YSybedtBs...(생략됨)
EOF

설정 파일 권한 설정

권한이 있는 경우에만 접근할 수 있도록 설정 파일의 권한을 수정합니다.

$ sudo chmod 600 /opt/mastodon/application.env
$ sudo chmod 600 /opt/mastodon/database.env

nginx 설정 파일 생성

nginx가 Mastodon 인스턴스로 트래픽을 라우팅해줄 수 있도록 설정 파일을 만들어주세요.

  • mastodon.example.com으로 적혀 있는 도메인은 사용하시려는 도메인으로 교체해주세요.
  • 웹 주소와 로컬 주소를 다르게 설정하실 경우, 여기에는 웹 주소로 사용하실 도메인을 넣어주세요.
  • 필요하신 경우 설정을 적절하게 고쳐주세요.
$ cat << 'EOF' | sudo tee /etc/nginx/sites-available/mastodon
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

upstream backend {
    server 127.0.0.1:3000 fail_timeout=0;
}

upstream streaming {
    server 127.0.0.1:4000 fail_timeout=0;
}

proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=CACHE:10m inactive=7d max_size=1g;

server {
    if ($host = mastodon.example.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot

    listen 80;
    server_name mastodon.example.com;
    return 404; # managed by Certbot
}

server {
    listen 443 ssl http2; # managed by Certbot
    server_name mastodon.example.com;

    ssl_certificate /etc/letsencrypt/live/mastodon.example.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/mastodon.example.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

    keepalive_timeout    70;
    sendfile             on;
    client_max_body_size 80m;

    root /opt/mastodon/public;

    gzip on;
    gzip_disable "msie6";
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_buffers 16 8k;
    gzip_http_version 1.1;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml image/x-icon;

    add_header Strict-Transport-Security "max-age=31536000" always;

    location / {
        try_files $uri @proxy;
    }

    location ~ ^/(system/accounts/avatars|system/media_attachments/files) {
        add_header Cache-Control "public, max-age=31536000, immutable";
        add_header Strict-Transport-Security "max-age=31536000" always;
        root /opt/mastodon/;
        try_files $uri @proxy;
    }

    location ~ ^/(emoji|packs) {
        add_header Cache-Control "public, max-age=31536000, immutable";
        add_header Strict-Transport-Security "max-age=31536000" always;
        try_files $uri @proxy;
    }

    location /sw.js {
        add_header Cache-Control "public, max-age=0";
        add_header Strict-Transport-Security "max-age=31536000" always;
        try_files $uri @proxy;
    }

    location @proxy {
        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;
        proxy_set_header Proxy "";
        proxy_pass_header Server;

        proxy_pass http://backend;
        proxy_buffering on;
        proxy_redirect off;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;

        proxy_cache CACHE;
        proxy_cache_valid 200 7d;
        proxy_cache_valid 410 24h;
        proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
        add_header X-Cached $upstream_cache_status;
        add_header Strict-Transport-Security "max-age=31536000" always;

        tcp_nodelay on;
    }

    location /api/v1/streaming {
        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;
        proxy_set_header Proxy "";

        proxy_pass http://streaming;
        proxy_buffering off;
        proxy_redirect off;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;

        tcp_nodelay on;
    }

    error_page 500 501 502 503 504 /500.html;
}
EOF

파일의 링크를 생성해 활성화합니다.

$ sudo ln -s /etc/nginx/sites-available/mastodon /etc/nginx/sites-enabled/

(선택사항) 웹 주소와 로컬 주소를 다르게 설정하실 경우

웹 주소와 로컬 주소를 다르게 설정하는 경우, 로컬 주소로 설정하려고 하는 도메인의 일부 경로가 Mastodon 인스턴스를 가리키도록 해 줘야 합니다. 이를 위해 추가적인 nginx 설정 파일을 생성합니다.

  • 기존에 사용하시던 설정이 있는 경우 아래 내용을 참고해 적절히 수정해주세요.
    • HTTP/2 프로토콜 지원 및 ## mastodon .well-known 주석 처리가 되어 있는 location 항목이 핵심적인 부분입니다.
$ cat << 'EOF' | sudo tee /etc/nginx/sites-available/default
server {
    if ($host = example.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot

    listen 80;
    server_name example.com;
    return 404; # managed by Certbot
}

server {
    listen 443 ssl http2; # managed by Certbot
    server_name mastodon.example.com;

    ssl_certificate /etc/letsencrypt/live/mastodon.example.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/mastodon.example.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

    keepalive_timeout    70;
    sendfile             on;
    client_max_body_size 80m;

    root /var/www/html;
    index index.html index.htm index.nginx-debian.html;

    gzip on;
    gzip_disable "msie6";
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_buffers 16 8k;
    gzip_http_version 1.1;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml image/x-icon;

    add_header Strict-Transport-Security "max-age=31536000" always;

    location / {
        try_files $uri $uri/ =404;
    }

    ## mastodon .well-known
    location ~ ^/\.well-known/(host-meta|webfinger) {
        return 301 https://mastodon.example.com$request_uri;
    }
}
EOF

파일의 링크를 생성해 활성화합니다.

$ sudo ln -s /etc/nginx/sites-available/default /etc/nginx/sites-enabled/

nginx 재실행

설정 파일을 적용하기 위해 nginx를 재시작합니다.

$ sudo service nginx restart

Docker 이미지 받아오기

Docker 이미지를 받아옵니다.

$ sudo docker-compose -f /opt/mastodon/docker-compose.yml pull
Pulling redis          ... done
Pulling redis-volatile ... done
Pulling elasticsearch  ... done
Pulling website        ... done
Pulling shell          ... done
Pulling streaming      ... done
Pulling sidekiq        ... done

mastodon 서비스 설정

Mastodon 서비스를 설정합니다.

$ cat << EOF | sudo tee /etc/systemd/system/mastodon.service
[Unit]
Description=Mastodon service
After=docker.service

[Service]
Type=oneshot
RemainAfterExit=yes

WorkingDirectory=/opt/mastodon
ExecStart=/usr/bin/docker-compose -f /opt/mastodon/docker-compose.yml up -d
ExecStop=/usr/bin/docker-compose -f /opt/mastodon/docker-compose.yml down

[Install]
WantedBy=multi-user.target
EOF
$ sudo systemctl daemon-reload

데이터베이스 초기화

데이터베이스 마이그레이션을 수행하여 데이터베이스를 초기화합니다.

$ sudo docker-compose -f /opt/mastodon/docker-compose.yml run --rm shell bundle exec rake db:migrate

실행 과정

mastodon 서비스 실행

서비스를 활성화하고 시작합니다.

$ sudo systemctl enable --now mastodon.service

컨테이너가 전부 실행되었는지 확인합니다.

$ sudo docker-compose -f /opt/mastodon/docker-compose.yml ps
          Name                         Command                  State                     Ports               
--------------------------------------------------------------------------------------------------------------
mastodon_elasticsearch_1    /bin/tini -- /usr/local/bi ...   Up (healthy)
mastodon_redis-volatile_1   docker-entrypoint.sh redis ...   Up (healthy)
mastodon_redis_1            docker-entrypoint.sh redis ...   Up (healthy)
mastodon_shell_1            /usr/bin/tini -- /bin/bash       Exit 0
mastodon_sidekiq_1          /usr/bin/tini -- bundle ex ...   Up (healthy)   3000/tcp, 4000/tcp
mastodon_streaming_1        /usr/bin/tini -- node ./st ...   Up (healthy)   3000/tcp, 127.0.0.1:4000->4000/tcp
mastodon_website_1          /usr/bin/tini -- bash -c b ...   Up (healthy)   127.0.0.1:3000->3000/tcp, 4000/tcp

사용자 생성

사용하실 사용자를 생성합니다. USER_NAMEUSER_EMAIL을 사용하실 유저의 정보로 변경해 다음 명령어를 실행해주세요.

$ sudo docker-compose -f /opt/mastodon/docker-compose.yml run --rm shell bin/tootctl accounts create USER_NAME --email USER_EMAIL --confirmed --role admin
Creating mastodon_shell_run ... done
OK
New password: a2af76138ca9502b1d1e1956aa8727e8

(선택사항) 가입 비활성화

혼자만 인스턴스를 사용하실 경우 가입을 비활성화시킬 수 있습니다.

$ sudo docker-compose -f /opt/mastodon/docker-compose.yml run --rm shell  bin/tootctl settings registrations close
OK

Elasticsearch 인덱스 생성

다음 명령어를 실행해 인덱스를 생성합니다. 이 명령어는 오류가 발생하면서 실행에 실패할 수도 있습니다. 이 경우 하루정도 계정을 사용하신 뒤에 명령어를 다시 실행해보세요.

$ sudo docker-compose -f /opt/mastodon/docker-compose.yml run --rm shell tootctl search deploy
Creating mastodon_shell_run ... done
2/2 |=======================================================================| Time: 00:00:01 (2 docs/s)
Indexed 2 records, de-indexed 0

클린업 작업 서비스 설정

디스크 공간을 아끼기 위해 오래된 캐시 파일을 삭제하는 작업을 구성합니다.

다운로드된 미디어 파일 삭제 서비스

$ cat << EOF | sudo tee /etc/systemd/system/mastodon-media-remove.service
[Unit]
Description=Mastodon - media remove service
Wants=mastodon-media-remove.timer

[Service]
Type=oneshot
StandardError=null
StandardOutput=null

WorkingDirectory=/opt/mastodon
ExecStart=/usr/bin/docker-compose -f /opt/mastodon/docker-compose.yml run --rm shell tootctl media remove

[Install]
WantedBy=multi-user.target
EOF
$ cat << EOF | sudo tee /etc/systemd/system/mastodon-media-remove.timer
[Unit]
Description=Schedule a media remove every week

[Timer]
Persistent=true
OnCalendar=Sat *-*-* 00:00:00
Unit=mastodon-media-remove.service

[Install]
WantedBy=timers.target
EOF

프리뷰 카드 삭제 서비스

$ cat << EOF | sudo tee /etc/systemd/system/mastodon-preview_cards-remove.service
[Unit]
Description=Mastodon - preview cards remove service
Wants=mastodon-preview_cards-remove.timer

[Service]
Type=oneshot
StandardError=null
StandardOutput=null

WorkingDirectory=/opt/mastodon
ExecStart=/usr/bin/docker-compose -f /opt/mastodon/docker-compose.yml run --rm shell tootctl preview_cards remove

[Install]
WantedBy=multi-user.target
EOF
$ cat << EOF | sudo tee /etc/systemd/system/mastodon-preview_cards-remove.timer
[Unit]
Description=Schedule a preview cards remove every week

[Timer]
Persistent=true
OnCalendar=Sat *-*-* 00:00:00
Unit=mastodon-preview_cards-remove.service

[Install]
WantedBy=timers.target
EOF

클린업 작업 서비스 활성화

$ sudo systemctl daemon-reload
$ sudo systemctl enable --now mastodon-preview_cards-remove.timer
$ sudo systemctl enable --now mastodon-media-remove.timer
$ sudo systemctl list-timers
NEXT                        LEFT           LAST                        PASSED       UNIT                                ACTIVATES
...
Sat 2022-11-26 00:00:00 KST 6 days left    n/a                         n/a          mastodon-media-remove.timer         mastodon-media-remove.service
Sat 2022-11-26 00:00:00 KST 6 days left    n/a                         n/a          mastodon-preview_cards-remove.timer mastodon-preview_cards-remove.service
...

15 timers listed.
Pass --all to see loaded but inactive timers, too.

기타 사항

여기까지 작업하셨으면 웹 브라우저로 설정하신 웹 주소를 접속했을 때 Mastodon 웹 페이지가 정상적으로 실행되어야 합니다. 만약 오류가 발생하는 경우 docker logs 명령어를 활용해 각 컨테이너에 문제가 있는지 확인하시기 바랍니다.

그러면 즐거운 마스토돈 생활 되시길 바랍니다! 괜찮다면 제 계정도 놀러와주세요.

AiOO (@AiOO@aioo.ooo)
18 게시물, 21 팔로잉, 22 팔로워 · 여러 인스턴스를 전전하다가 결국 https://mastodon.aioo.ooo 인스턴스를 운영합니다.프로필 사진은 지금은 잃어버린 내스급 비공식 굿즈 망충피쮸 인형입니다. ㅠㅠ