41 6E 74 61 72 63 74 69 63 61

You know what is it, right?

《使用 WriteFreely 搭建聯邦宇宙博客站點》

WriteFreely 是一個能通過 ActivityPub 協議接入聯邦宇宙的博客實例框架,使用 Go 進行實現(沒想到啊沒想到)。實話説搭建起來基本上沒有難度,最簡單的實現就是裝個 MySQL 然後直接作爲服務啓動,完事。但是由於太久沒折騰服務器了,再加上又想挂反代又想搞 Docker,結果折騰了將近一天(中間睡了一覺)才把這玩意建立起來。

WriteFreely 自身是不支持上傳圖片的,想要在 blog 中插入圖片就需要一個外部的圖床。一不做二不休,乾脆也在服務器上部署了 Piwigo 來進行支持。

簡述

Nginx + WriteFreely + Piwigo + MySQL,支持 httphttps,最終域名為 blog.penguinsoup.me

MySQL in Docker

首先要先把服務器設置起來。考慮到其他的應用也可能用這個 MySQL,因此最後沒有選擇將其合并到 Docker Compose 中,而是作爲一個單獨的容器,通過 3306 端口暴露自身的服務。另外,還考慮使用 Docker Secrets 來傳遞用戶密碼。

--- working_directory
 |--- docker-compose.yaml
 |--- config
 | |--- my.cnf
 |--- secrets
 | |--- mysql-root

由於 MySQL 某個(某個)版本加入的改變驗證方式的默認設置(*企鵝粗口*),因此需要修改一下默認設置來使通過密碼登入賬戶成爲可能:

# config/my.cnf
[mysqld]
mysql_native_password=ON
default-time-zone='+00:00' # writefreely required

再就是在 secrets/mysql-root 中放入管理員賬戶的密碼,並準備好 docker-compose.yaml

version: "3"

services:
  mysql:
    image: mysql:8.4.2
    container_name: mysql
    ports:
      - 3306:3306
    networks:
      - mysql-bridge
    volumes:
      - /path/to/working_directory/config:/etc/mysql/conf.d/
      - /path/to/working_directory/logs:/var/log/mysql
      - /path/to/working_directory/secrets:/run/secrets
    environment:
      - MYSQL_ROOT_PASSWORD_FILE=/run/secrets/mysql-root
    restart: unless-stopped

networks:
  mysql-bridge:
    external: true

配置 Docker Network 並啓動:

$ docker network create --driver bridge mysql-bridge
$ docker compose up -d

$ docker inspect mysql-bridge
...
  Container {
    "hash code": {
      "Name": "mysql",
      "IPv4Address": "172.xx.xx.xx" # that's mysql host addr in other containers
    }
  }
...

從外部連入(即便 client 就在服務器,的也需要手動指定爲 remote):

mysql -u root -h localhost -P 3306 --protocol=tcp -p # client on server

最後按照 WriteFreely 和 Piwigo 的指引設置好相關的數據庫,並創建一個給外部連入用的賬戶即可:

CREATE DATABASE writefreely CHARACTER SET latin1 COLLATE latin1_swedish_ci;
CREATE DATABASE pwigo;
CREATE USER '${USER}'@'%' IDENTIFIED WITH mysql_native_password BY 'y0Ur_p^sswD';
GRANT ALL PRIVILEGES ON writefreely.* TO '${User}'@'%';
GRANT ALL PRIVILEGES ON piwigo.* TO '${User}'@'%';
FLUSH PRIVILEGES;

由於其他容器訪問 MySQL 都是通過 Docker

Nginx

接下來要設置好反向代理(如果服務器只提供一個網頁服務就不用,但一般不會有人租個服務器就單單搭一個 blog 吧,嗯?),這樣就可以把通過不同域名映射到同一 IP 的同端口請求轉發到不同的實際應用上進行處理。

--- working_directory
 |--- {blog,img}.penguinsoup.me.conf
 |--- includes
 | |--- {proxy,ssl,gzip}.conf
 |--- ssl
 | |--- yourdomain.{crt,key} # use acme.sh or something to issue
 |--- logs
 | |--- {blog,img}.penguinsoup.me
 |   |--- {access,error}.log # created by nginx

配置文件如下:

# proxy.conf
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_http_version 1.1;ssl_session_timeout 1d;

# ssl.conf
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

# gzip.conf
gzip on;
gzip_types
  application/javascript
  application/x-javascript
  application/json
  application/rss+xml
  application/xml
  image/svg+xml
  image/x-icon
  application/vnd.ms-fontobject
  application/font-sfnt
  text/css
  text/plain;
gzip_min_length 256;
gzip_comp_level 5;
gzip_http_version 1.1;
gzip_vary on;

# blog.penguinsoup.me.conf
server {
    # listening server:port
    listen 80;
    listen [::]:80;
    listen 443 ssl; # optional: https
    listen [::]:443 ssl; # optional: https
    server_name blog.penguinsoup.me;

    # optional: logs
    access_log /path/to/working_directory/logs/access.log;
    error_log /path/to/working_directory/logs/error.log warn;

    # optional: enable compression
    include /path/to/working_directory/includes/gzip.conf;

    # optional: https certificate
    ssl_certificate /path/to/working_directory/ssl/blogpenguinsoup.crt;
    ssl_certificate_key /path/to/working_directory/ssl/blogpenguinsoup.key;
    include /etc/nginx/includes/ssl.conf;

    # webfinger proxy
    location ~ ^/.well-known/(webfinger|nodeinfo|host-meta)/ {
        include /path/to/working_directory/includes/proxy.conf;
        proxy_pass http://localhost:8080; # default port of writefreely
        proxy_redirect off;
    }

    # static files
    location ~ ^/(css|img|js|fonts)/ {
        root /path/to/your/static;
        expires 12M;
    }

    # main proxy
    location / {
        include /path/to/working_directory/includes/proxy.conf;
        proxy_pass http://localhost:8080; # default port of writefreely
        proxy_redirect off;
    }
}

# img.penguinsoup.me
server {
    # listening server:port
    listen 80;
    listen [::]:80;
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name img.penguinsoup.me;

    # logs
    access_log /path/to/working_directory/logs/img.penguinsoup.me/access.log;
    error_log /path/to/working_directory/logs/img.penguinsoup.me/error.log warn;

    # enable compression
    include /path/to/working_directory/includes/gzip.conf;

    # https certificate
    ssl_certificate /path/to/working_directory/ssl/imgpenguinsoup.crt;
    ssl_certificate_key /path/to/working_directory/ssl/imgpenguinsoup.key;
    include /path/to/working_directory/includes/ssl.conf;

    # main proxy
    location / {
        include /path/to/working_directory/includes/proxy.conf;
        proxy_pass http://localhost:7999;
        proxy_redirect off;
    }
}

別忘了生成域名對應的 HTTPS 證書並安裝到 ssl/ 下面,具體的操作方式可以參照 這篇文章

Nginx 就不扔進容器了,這個還是放在 host 上比較方便一點。通過包管理器或者別的方式安裝之後,在 /etc/nginx/site-enabled 下面創造 blog 和 img 配置文件的軟鏈接,最後記得重新啓動 service

Piwigo in Docker

直接上 docker-compose.yaml

version: "3"

services:
  piwigo:
    image: lscr.io/linuxserver/piwigo:14.5.0
    container_name: piwigo
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Asia/Shanghai
    volumes:
      - /path/to/photos:/gallery
    ports:
      - 7999:80
    networks:
      - mysql-bridge
    restart: unless-stopped

networks:
  mysql-bridge:
    external: true

啓動后訪問一下,設置好就可以了。別忘了 MySQL 的地址是上面 inspect mysql-bridge 的時候的地址。

WriteFreely in Docker

最開始的時候我是想把這個丟進 Docker 裏面的,然而因爲預編譯版本扔進容器會缺依賴跑不起來,然後又懶得在容器裏編譯了,最後就直接用預編譯文件跑在 host 上了。後面因爲某個(某個)圖床把整個 Docker 搞崩潰了,想著就弄一下吧,結果在官方倉庫的 docker-compose.yaml 裏面發現了這麽一行

image: writeas/writefreely:latest

好啊!原來你們有鏡像啊!那就老規矩,docker-compose.yaml

version: "3"

services:
  writefreely:
    image: writeas/writefreely:latest
    container_name: writefreely
    volumes:
      - /path/to/working_directory/config.ini:/go/config.ini
      - /path/to/working_directory/keys:/go/keys
      - /path/to/working_directory/static:/go/static
    ports:
      - 8080:8080
    networks:
      - mysql-bridge
    user: "0:0"
    restart: unless-stopped

networks:
  mysql-bridge:
    external: true

目錄結構:

--- working_directory
 |--- docker-compose.yaml
 |--- config.ini # created by wf
 |--- keys
 | |--- # files created by wf
 |--- static # copy from binary package

接下來要進行設置,然而問題來了:沒有 config.inikeys 就不能啓動,但是不啓動就沒有這些配置文件()。所以,此時要先直接啓動容器來進行配置:

$ docker container run -it --rm \
> -v mount config.ini \
> -u "0:0" \ # start up as root
> writeas/writefreely:latest --config
# don't forget: database host is the addr found in `inspect mysql-bridge`

$ docker container run -it --rm \
> -v mount keys \
> -u "0:0" \ # start up as root
> writeas/writefreely:latest --gen-keys 

接下來要修改一項 config.ini 中的設置,否則無法在容器中運行:

bind = localhost
     ->
bind = 0.0.0.0

最後 compose up,然後就可以愉快地使用啦!

 
阅读更多

《使用 acme.sh 簽發 HTTPS 證書》

請選擇進行單人副本時的難度:非常簡單

安裝

$ curl https://get.acme.sh | sh -s email=${YOUR_EMAIL}

這條命令會將 acme.sh 自動安裝到 ~/.acme.sh 下,並創建一個每天檢查證書是否即將過期的 cronjob

簽發並安裝證書

這裏從 Let's Encrypt 簽發:

$ sudo ./acme.sh --issue -d ${YOUR_DOMAIN} --standalone \
> --keylength ec-256 --server letsencrypt --force # when sudo: --force

接下來將證書安裝到提供服務的目錄下:

$ sudo ./acme.sh --installcert -d ${YOUR_DOMAIN} \
> --fullchain-file /path/to/your/directory/${YOUR_DOMAIN}.crt \ # certificate
> --key-file /path/to/your/directory/${YOUR_DOMAIN}.crt \ # encrypt key
> --reloadcmd "if needed" # reload service after renewed

實際上無論是證書還是密鑰,其文件名都是隨意的(只要提供服務的應用正確引用了就行),這裏僅僅是提供了一個方便管理的實例。

 
Read more...