NAS系列-2: 应用部署

237 阅读11分钟

上一篇已经部署ddns,成功后在外网使用域名是可以正常ping通的。本篇开始部署一下常用的应用,完善NAS的使用场景。没办法,最近太忙了,这个内容又多,先凑活发出来,后面再修修补补吧。

应用需求

  1. nginx:统一访问入口,方便应用的网络管理。
  2. acme.shhttps证书生成脚本,外网访问加密还是有必要的。
  3. immich:相册服务器,我个人搭建NAS最主要的使用场景。
  4. nextcloud:网盘应用,个人文件备份使用,包括手机的整机备份、图片文件、通话录音文件、重要文档等。
  5. vaultwarden:密码管理工具,bitwarden的开源版,实际需求看个人。
  6. jellyfin:家庭影音系统,emby硬解要买授权,客户端也要买,预算有限,所以选择开源的jellyfin
  7. qBittorrentjellyfin都部署了,下载的也顺便装了吧。
  8. samba:是的,内网文件共享也用docker
  9. sun-panel:导航面板,我主要是给上面那些应用导航用的,实际需求看个人。

上述应用,除了12,其他都属于个人喜好,同时所有的部署方式都会在本篇更新,看我文章的各位自己根据自己需求决定是否部署。

部署须知

应用部署使用了nginx做统一的入口做流量分发,因此有以下几点需要注意:

  • 应用端口不做映射,无法直接访问,统一通过nginx访问
  • nginx的配置,统一使用域名访问应用,因此应用指定的ip是多少,对访问没有影响
  • nginx访问的域名,是容器名称,和container_name对应
  • 部分应用映射挂载的目录,需要root权限才可以编辑、甚至读取
  • 每次修改nginx的配置,都需要重新加载才能生效
  • ssl证书90天一签,证书更新后nginx容器需要重新启动

应用部署

本节内容因为应用较多,且有些应用部署比较复杂,因此章节会比较长,不过还好,掘金这里右边可以自动生成目录,各位直接跳转即可。
上一篇已经部署过ddns,这里的工作是在上一篇中的docker-compose.yml.env添加新应用。
注意:yml文件对缩进非常严格,最好统一使用tab
部署前提:域名为example.comlinux下执行这些操作的用户名为admin,其中文件映射的路径按需更改!

acme.sh

假设在阿里云买了一个example.com的域名,要对这个域名上证书,使用acme.sh自动申请。编辑docker-compose.yml,添加以下内容

# 我知道看这文章的人不一定都懂下面的配置,这里统一说明一下:
# services 这个块里写的就是我们要部署的应用,一个文件里只能有一个 services 块
# 参考上一个章节的 ddns,如果本身存在 services 了,就只要把下面 services 块内的内容复制过去就行
# 注意缩进,acme.sh 和 ddns 同级,因此缩进应相同
services:
  acme.sh:
    image: neilpang/acme.sh@sha256:f7a2e1a19495d00fea99baaa4eec6329fd3755ef5d2b62401f7f49968b98eb6e
    container_name: came.sh
    restart: unless-stopped
    volumes:
      - ${SSL_PATH}:/acme.sh
    environment:
      Ali_Key: ${Ali_Key}
      Ali_Secret: ${Ali_Secret}
    command: daemon
    networks:
      nginx:
        ipv4_address: 172.18.0.2
        ipv6_address: fd00::2

此处Ali_KeyAli_Secretddns配置文件中的idtoken对应,是同一个密钥对,这里使用变量形式引用,因此需要在.env文件中添加对应变量

# acme.sh
SSL_PATH=/home/admin/docker-data/nginx/ssl
Ali_Key=*******
Ali_Secret=*******

这里直接将ssl的保存路径放到nginx文件夹下,方便nginx配置。配置完成后执行docker-compose up -d创建容器。
容器创建完成后执行以下命令生成ssl证书

# 先创建用户
docker exec -it came.sh --register-account -m my@email.com
# 执行证书生成,注意:泛域名证书需要同时配置主域名
docker exec -it came.sh --issue --dns dns_ali -d www.example.com -d *.example.com

docker内已经自带了cron定时任务,只要docker在运行,每天都会检查证书有效期并在过期前自动更新,cron任务具体为

46 0 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" --config-home "/acme.sh" > /proc/1/fd/1 2>/proc/1/fd/2
immich

immich目前更新比较频繁,还是推荐锁定版本使用。immich有多个配套的应用组件,组件版本也有对应的要求,以下是截至1.105.1版本可用的部署配置

services:
  immich-server:
    container_name: immich_server
    # 南京大学镜像站加速,ghcr.nju.edu.cn替换ghcr.io
    image: ghcr.nju.edu.cn/immich-app/immich-server@sha256:658b40420d7a39d6eb34c797cec8d36ff315f5adb168301aaf27dc4eafc8e228
    command: ["start.sh", "immich"]
    volumes:
      - ${IMMICH_UPLOAD_PATH}:/usr/src/app/upload
      - /etc/localtime:/etc/localtime:ro
    depends_on:
      - redis
      - immich_postgres
    environment:
      DB_PASSWORD: ${DB_PASSWORD}
      DB_USERNAME: ${DB_USERNAME}
      DB_DATABASE_NAME: ${DB_DATABASE_NAME}
      DB_HOSTNAME: ${DB_HOSTNAME}
      REDIS_HOSTNAME: ${REDIS_HOSTNAME}
    restart: unless-stopped
    networks:
      nginx:
        ipv4_address: 172.18.0.3
        ipv6_address: fd00::3

  immich-microservices:
    container_name: immich_microservices
    # 南京大学镜像站加速,ghcr.nju.edu.cn替换ghcr.io
    image: ghcr.nju.edu.cn/immich-app/immich-server@sha256:658b40420d7a39d6eb34c797cec8d36ff315f5adb168301aaf27dc4eafc8e228
    # extends:
    #   file: hwaccel.yml
    #   service: hwaccel
    command: ["start.sh", "microservices"]
    volumes:
      - ${IMMICH_UPLOAD_PATH}:/usr/src/app/upload
      - /etc/localtime:/etc/localtime:ro
    depends_on:
      - redis
      - immich_postgres
    environment:
      DB_PASSWORD: ${DB_PASSWORD}
      DB_USERNAME: ${DB_USERNAME}
      DB_DATABASE_NAME: ${DB_DATABASE_NAME}
      DB_HOSTNAME: ${DB_HOSTNAME}
      REDIS_HOSTNAME: ${REDIS_HOSTNAME}
    restart: unless-stopped
    networks:
      nginx:
        ipv4_address: 172.18.0.4
        ipv6_address: fd00::4

  immich-machine-learning:
    container_name: immich_machine_learning
    # 南京大学镜像站加速,ghcr.nju.edu.cn替换ghcr.io
    image: ghcr.nju.edu.cn/immich-app/immich-machine-learning@sha256:2568d563f69b82126e3a4105eef577c2f1a8f33701cd3a7ef7b936d061bc9658
    volumes:
      - ${IMMICH_MODEL_CACHE_PATH}:/cache
    restart: unless-stopped
    # 开启代理,否则模型无法下载
    # environment:
    #   - HTTP_PROXY=
    #   - HTTPS_PROXY=
    networks:
      nginx:
        ipv4_address: 172.18.0.5
        ipv6_address: fd00::5

  redis:
    container_name: immich_redis
    image: redis:6.2-alpine@sha256:51d6c56749a4243096327e3fb964a48ed92254357108449cb6e23999c37773c5
    restart: unless-stopped
    networks:
      nginx:
        ipv4_address: 172.18.0.6
        ipv6_address: fd00::6

  immich_postgres:
    container_name: immich_postgres
    image: tensorchord/pgvecto-rs:pg14-v0.1.11@sha256:90724186f0a3517cf6914295b5ab410db9ce23190a2d9d0b9dd6463e3fa298f0
    environment:
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_USER: ${DB_USERNAME}
      POSTGRES_DB: ${DB_DATABASE_NAME}
    volumes:
      - ${IMMICH_PG_DATA_PATH}:/var/lib/postgresql/data
    restart: unless-stopped
    networks:
      nginx:
        ipv4_address: 172.18.0.7
        ipv6_address: fd00::7

以上是根据官方部署文档的docker-compose.yml文件略加修改而来,其中多个变量,需在.env中定义

# immich
# 图片上传保存位置
IMMICH_UPLOAD_PATH=/home/admin/docker-data/immich/upload
# 人脸识别等功能需要使用的模型保存位置
IMMICH_MODEL_CACHE_PATH=/home/admin/docker-data/immich/model-cache
# 数据库文件保存位置
IMMICH_PG_DATA_PATH=/home/admin/docker-data/immich/pgdata

# 官方的说明,可以指定版本,但是部署时锁定了版本,这个可以不设置
# The Immich version to use. You can pin this to a specific version like "v1.71.0"
# IMMICH_VERSION="v1.98.2"

# 数据库的密码,建议复杂点
# Connection secret for postgres. You should change it to a random password
DB_PASSWORD="passw0rd"

# 以下4个,跟应用的环境变量有关,最好不做更改
# The values below this line do not need to be changed
DB_HOSTNAME=immich_postgres
DB_USERNAME=postgres
DB_DATABASE_NAME=immich
REDIS_HOSTNAME=immich_redis

如果客户端版本过高,服务器版本过低,将immich_server中的sha256更换成更新版本的校验值,然后重新执行docker-compose up -d即可

vaultwarden

vaultwarden是使用rust实现的开源版本的bitwarden,功能上有些小差异,但是基本使用是无感的,部署也很简单

services:
  vaultwarden:
    image: vaultwarden/server@sha256:edb8e2bab9cbca22e555638294db9b3657ffbb6e5d149a29d7ccdb243e3c71e0
    container_name: vaultwarden
    restart: unless-stopped
    environment:
      WEBSOCKET_ENABLED: "true" # Enable WebSocket notifications.
      # ADMIN_TOKEN: ${VAULTWARDEN_ADMIN_TOKEN}
      TZ: "Asia/Shanghai"
    volumes:
      - ${VAULTWARDEN_PATH}:/data
      - /etc/localtime:/etc/localtime:ro
    networks:
      nginx:
        ipv4_address: 172.18.0.8
        ipv6_address: fd00::8

需要指定密码数据库的存储位置,由VAULTWARDEN_PATH指定

# vaultwarden
VAULTWARDEN_PATH=/home/admin/docker-data/vaultwarden/data

vaultwarden有很多配置,可以后续专门出一个章节讲解,这里主要提一下ADMIN_TOKEN,只有environmentconfig文件都存在该值的前提下,管理页面才可用

nextcloud

nextcloud是个很笨重的网盘应用,配置也复杂,如果不懂怎么去维护,建议干脆还是别用了

services:
  nextcloud:
    image: nextcloud@sha256:44472f93c757f265585642d8f1099d74812f00bc56ec514f271b5f1477e5d1a1
    container_name: nextcloud
    restart: unless-stopped
    volumes:
      - ${NEXTCLOUD_MAIN_PATH}:/var/www/html
    # extra_hosts:
    #   - "host.docker.internal:host-gateway"
    environment:
      MYSQL_HOST: ${NEXTCLOUD_MARIADB_HOST}
      MYSQL_USER: ${NEXTCLOUD_MARIADB_USER}
      MYSQL_PASSWORD: ${NEXTCLOUD_MARIADB_PASSWORD}
    networks:
      nginx:
        ipv4_address: 172.18.0.9
        ipv6_address: fd00::9

  mariadb:
    image: mariadb@sha256:93fdee573c8294bc2b929b7e648dafb70238c1583bbc95a4947ad3885f1069a6
    container_name: mariadb
    restart: unless-stopped
    volumes:
      - ${NEXTCLOUD_MARIADB_PATH}:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: ${NEXTCLOUD_MARIADB_ROOT_PASSWORD}
      MYSQL_DATABASE: ${NEXTCLOUD_MARIADB_DB}
      MYSQL_USER: ${NEXTCLOUD_MARIADB_USER}
      MYSQL_PASSWORD: ${NEXTCLOUD_MARIADB_PASSWORD}
    networks:
      nginx:
        ipv4_address: 172.18.0.10
        ipv6_address: fd00::10
        aliases:
          - mariadb

对应的.env变量定义为

# nextcloud
# 上传文件路径
NEXTCLOUD_MAIN_PATH=/home/admin/docker-data/nextcloud/main
# 数据库路径
NEXTCLOUD_MARIADB_PATH=/home/admin/docker-data/nextcloud/mariadb
# 数据库名称,可更改
NEXTCLOUD_MARIADB_DB="nextcloud"
# 数据库主机名,与 mariadb 的容器名对应
NEXTCLOUD_MARIADB_HOST="mariadb"
# 数据库用户名
NEXTCLOUD_MARIADB_USER="nextcloud"
# 数据库 root 用户密码,自定义
NEXTCLOUD_MARIADB_ROOT_PASSWORD="passw0rd"
# 数据库 nextcloud 用户密码,自定义
NEXTCLOUD_MARIADB_PASSWORD="passw0rd"

执行docker-compose up -d即可完成容器的创建,应用配置,需要编辑/home/admin/docker-data/nextcloud/main/config/config.php,编辑该文件需要root权限,以下是需要修改的项,没有列出来的不需要更改

'trusted_domains' => 
  array (
    # 访问域名,根据自己实际情况填写
    0 => 'nextcloud.example.com',
  ),

填写完成后打开页面,完善服务配置即可,主要是数据库配置。

jellyfin

首先声明,根据需求,这里不使用nvidia显卡做硬件加速,默认使用intel核显

services:
  jellyfin:
    image: jellyfin/jellyfin@sha256:41fc4f9a51f638930bf16eace81acacbafaf26436d0efc0b0edd9447cb134a2c
    container_name: jellyfin
    restart: unless-stopped
    volumes:
      - ${QBT_DOWNLOADS}:/media
      - ${JELLYFIN_CACHE_PATH}:/cache
      - ${JELLYFIN_CONFIG_PATH}:/config
      - ${JELLYFIN_FONTS_PATH}:/usr/share/fonts/truetype/dejavu
    environment:
      - TZ=Asia/Shanghai
      - PGID=0
      - PUID=0
    devices: # 硬件加速
      - /dev/dri
    extra_hosts:
      # 刮削使用
      - "api.themoviedb.org:13.226.225.4"
      - "api.themoviedb.org:13.226.225.52"
      - "api.themoviedb.org:13.226.225.73"
      - "api.themoviedb.org:13.226.225.44"
      - "image.tmdb.org:143.244.49.183"
    networks:
      nginx:
        ipv4_address: 172.18.0.11
        ipv6_address: fd00::11

对应的.env对象定义为

# jellyfin 一般而言,除了字体路径需要手动处理,缓存和配置路径一般都不需要很关注

# QBT_DOWNLOADS 是容器扫描媒体的路径,配合 qBittorrent 使用,因此由 qBittorrent 定义,这里不用写
# 如果个人本身就有媒体库,可以直接挂载上来,qBittorrent 那边下载路径也改成媒体库路径即可

# 缓存路径
JELLYFIN_CACHE_PATH=/home/admin/docker-data/jellyfin/cache
# 配置路径
JELLYFIN_CONFIG_PATH=/home/admin/docker-data/jellyfin/config
# 字体路径
JELLYFIN_FONTS_PATH=/home/admin/docker-data/jellyfin/fonts
qBittorrent

qBittorrent是个bt下载工具,也广泛在各大pt站使用

services:
  qbittorrent:
    image: lscr.io/linuxserver/qbittorrent@sha256:3b563efc0010bd3cf4e14bc1baf33dfbaf46bd3992a40793779ba0db91f41281
    container_name: qbittorrent
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Etc/UTC
      - WEBUI_PORT=8080
      - TORRENTING_PORT=6881
    volumes:
      - ${QBT_CONFIG}:/config
      - ${QBT_DOWNLOADS}:/downloads
    restart: unless-stopped
    networks:
      nginx:
        ipv4_address: 172.18.0.12
        ipv6_address: fd00::12

对应.evn配置为

# qbittorrent
# 配置文件
QBT_CONFIG=/home/admin/docker-data/qbittorrent/config
# 下载路径,该路径同时挂载到 jellyfin
# 下载后 jellyfin 会自动扫描到对应路径的媒体库变化,自动刮削
QBT_DOWNLOADS=/home/admin/docker-data/media
samba

部署samba,才更像个NAS,可以给内网的电脑提供挂载路径,共享硬盘空间

services:
  samba:
    container_name: samba
    image: dockurr/samba@sha256:3de04fb29ff807bcf30c43529ce3d3f910d347c7db117202909bc373bf45fe03
    restart: on-failure
    volumes:
      - ${SAMBA_DIR}:/storage
      - ${SAMBA_MEDIA}:/media
      - ${SAMBA_CONFIG}:/etc/samba/smb.conf
    environment:
      USER: ${SAMBA_USER}
      PASS: ${SAMBA_PWD}
      # RW: true      # Optional, default true
      # UID: 1000    # Optional, default 1000
      # GID: 1000    # Optional, default 1000
    networks:
      nginx:
        ipv4_address: 172.18.0.13
        ipv6_address: fd00::13

对应.env配置为

# samba
# 共享路径,可以定义多个
SAMBA_DIR=/home/admin/docker-data/samba
# 添加多个路径时,需要先挂载
SAMBA_MEDIA=/home/admin/docker-data/media
# samba 账户名
SAMBA_USER=samba
# samba 账户密码
SAMBA_PWD=nishiyizhizhu
# 配置文件,可以在这里添加更多挂载点
SAMBA_CONFIG=/home/alpha/docker/samba/smb.conf

添加挂载点时编辑smb.conf文件,添加以下内容

# 与默认的 [Data] 结构一致
[media]
        # 对应容器内部挂载的路径
        path = /media
        comment = Shared
        valid users = @smb
        browseable = yes
        writable = yes
        read only = no
        force user = root
        force group = root
sun-panel

sun-panel是一个导航面板,详情可以查看应用的wiki

services:
  sun-panel:
    container_name: sun-panel
    image: hslr/sun-panel@sha256:3ea86b1478b9cfde2320ed57e6fdb7aef4ddad9fce61c8193189b4a410e375a9
    volumes:
      - ${DISK_A}:/DISK_A:ro
      - ${DISK_B}:/DISK_B:ro
      - ${PANEL_CONF}:/app/conf
    restart: unless-stopped
    networks:
      nginx:
        ipv4_address: 172.18.0.14
        ipv6_address: fd00::14

对应变量定义为

# sun-panel 做硬盘容量显示,需要有权限读取磁盘信息
# 可以在宿主机的磁盘挂载路径新建一个自定义名字的空文件夹,然后以只读方式挂载到容器中
# sun-panel 添加硬盘容量显示时选中容器中对应的容器挂载目录即可
# 注意,创建自定义名字的空文件夹需在容器创建前完成
DISK_A=/srv/DISK_A/sun-panel.stat
DISK_B=/srv/DISK_B/sun-panel.stat
# 配置文件,持久化配置
PANEL_CONF=/home/alpha/docker/sunpanel/conf
nginx

nginx是整个配置的重难点,要配置的内容非常多。

  • 默认配置生成 nignx并不能直接将默认配置文件映射出来,因此需要事先准备默认配置文件:
# 我个人喜欢锁死版本使用,读者可以直接 docker pull nginx 拉取最新版,但是我这里所有的步骤都是按我的版本来操作
# 新版是否一致,我不确定
docker pull nginx:mainline-alpine3.18-slim@sha256:d50b0d87b5d34da5649e3acfc969011b2012ab9be62b70f8fb97c4d6467a317a
# 先起一个 nginx
docker run --name nginx -d nginx
# 把默认的配置文件拿出来,权限不够就sudo
docker cp nginx:/etc/nginx ~/docker-data/nginx
# 清除该测试容器
docker stop nginx & docker rm nginx
  • 创建容器 默认配置拿到手后,编辑docker-compose.yml,添加以下内容
    services:
      nginx:
        image: nginx:mainline-alpine3.18-slim@sha256:d50b0d87b5d34da5649e3acfc969011b2012ab9be62b70f8fb97c4d6467a317a
        container_name: nginx
        restart: unless-stopped
        volumes:
          - ${NGINX_PATH}:/etc/nginx
        networks:
          nginx:
            ipv4_address: 172.18.0.254
            ipv6_address: fd00::fe
        ports:
          - 80:80   # 这里的 80 和 443 端口运营商一般都是禁用的,因此这里看自己需求换,右边是内部端口,跟配置文件要对应
          - 443:443 # 左边是实际外网能访问的端口,可以随意更换,大于 1000 且不被占用即可,非 80 和 443 端口访问时需要写上
          - 445:445 # samba 使用的端口,需要映射出来
    
    # 新建一个网络,把所有应用都放到同一个网络中,这样就可以使用容器名代替 ip 来访问,这个网络和 services 同级,也是只能有一个
    # 使用 ipv6 是为了 qBittorrent 这种应用在运行时也可以使用 ipv6
    # 这么写需要高版本的 docker-compose 才能识别,按上一个章节的步骤安装即可
    networks:
      nginx:
        driver: bridge
        ipam:
          driver: default
          config:
            - subnet: 172.18.0.0/24
            - subnet: fd00::/64
    
    继续编辑.env,定义NGINX_PATH变量的值,添加以下内容:
    # nginx
    NGINX_PATH=/home/admin/docker-data/nginx
    
    配置完成,执行docker-compose up -d即可创建nginx应用。
  • 配置应用代理 至此,应用部署完成,但是上述所有容器,都没有将端口从容器中映射出来,也就是直到现在,所有的容器都是不可以访问的,接下来就是配置nginx,让应用都可以正常访问。
    首先定义各个应用的访问地址:
    immich: immich.example.com
    nextcloud: nextcloud.example.com
    vaultwarden: vaultwarden.example.com
    jellyfin: jellyfin.example.com
    qbittorrent: qbittorrent.example.com
    分别做配置,首先修改/home/admin/docker-data/nginx/nginx.conf,以下是修改的项,没有列出来则不用修改
    # 新增,与 http 块同级
    stream {
            include /etc/nginx/stream/*.conf;
    }
    
    # 在http块中新增
    server {
            # http 默认跳转 https
            listen  80;
            server_name _;
            return  301 https://$host$request_uri;
    }
    
    server {
            listen [::]:443 ssl default_server;
            server_name _;
            # SSL
            ssl_certificate /etc/nginx/ssl/example.com_ecc/fullchain.cer;
            ssl_certificate_key /etc/nginx/ssl/example.com_ecc/example.com.key;
            location / {
                    return 404;
            }
    }
    
    include /etc/nginx/sites-enabled/*.conf;
    
    # 块中如果存在 include /etc/nginx/conf.d/*.conf; 需要注释掉
    
    定义安全头,先创建文件夹mkdir -p /home/admin/docker-data/nginx/conf.d/,再新建touch /home/admin/docker-data/nginx/conf.d/security.conf,新增以下内容
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Referrer-Policy "no-referrer-when-downgrade" always;
    add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
    
    • immich
      新建文件touch /home/admin/docker-data/nginx/sites-enabled/immich.conf,并添加以下内容
      server {
          listen [::]:443 ssl;
          server_name immich.example.com;
      
          client_max_body_size 0;
          
          # SSL
          ssl_certificate /etc/nginx/ssl/example.com_ecc/fullchain.cer;
          ssl_certificate_key /etc/nginx/ssl/example.com_ecc/example.com.key;
      
          # security headers
          include /etc/nginx/conf.d/security.conf;
      
          # reverse proxy
          location / {
              proxy_pass http://immich_server:3001;
      
              proxy_set_header Host              $http_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_http_version 1.1;
              proxy_set_header   Upgrade    $http_upgrade;
              proxy_set_header   Connection "upgrade";
              proxy_redirect off;
          }
      }
      
    • nextcloud
      新建文件touch /home/admin/docker-data/nginx/sites-enabled/nextcloud.conf,并添加以下内容
      server {
          listen [::]:443 ssl;
          server_name nextcloud.example.com;
      
          # set max upload size
          client_max_body_size 0;
          fastcgi_buffers 64 4K;
      
          # SSL
          ssl_certificate /etc/nginx/ssl/example.com_ecc/fullchain.cer;
          ssl_certificate_key /etc/nginx/ssl/example.com_ecc/example.com.key;
      
      
      
          include /etc/nginx/conf.d/security.conf;
      
          # . files
          location ^~ /.well-known {
              # The rules in this block are an adaptation of the rules
              # in `.htaccess` that concern `/.well-known`.
              location = /.well-known/carddav { 
                  return 301 /remote.php/dav/; 
              }
              location = /.well-known/caldav  { 
                  return 301 /remote.php/dav/; 
              }
              location /.well-known/acme-challenge    { 
                  try_files $uri $uri/ =404; 
              }
              location /.well-known/pki-validation    { 
                  try_files $uri $uri/ =404; 
              }
              # Let Nextcloud's API for `/.well-known` URIs handle all other
              # requests by passing them to the front-end controller.
              return 301 /index.php$request_uri;
          }
      
          # reverse proxy
          location / {
              proxy_pass http://nextcloud;
              proxy_http_version    1.1;
              proxy_cache_bypass    $http_upgrade;
              proxy_set_header Upgrade                      $http_upgrade;
              proxy_set_header Connection           "upgrade";
              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 X-Forwarded-Host     $host;
              proxy_set_header X-Forwarded-Port     $server_port;
          }
      
          # favicon.ico
          location = /favicon.ico {
              log_not_found off;
              access_log off;
          }
          # robots.txt
          location = /robots.txt {
              log_not_found off;
              access_log off;
          }
      
          # gzip
          gzip on;
          gzip_vary on;
          gzip_proxied any;
          gzip_comp_level 6;
          gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xmlapplication/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xmlapplication/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rimlocation.xloc text/vtt text/x-component text/x-cross-domain-policy;
      }
      
    • vaultwarden
      新建文件touch /home/admin/docker-data/nginx/sites-enabled/nextcloud.conf,并添加以下内容
      server {
      
          listen [::]:443 ssl;
          server_name vaultwarden.example.com;
      
          # set max upload size
          client_max_body_size 0;
          fastcgi_buffers 64 4K;
      
          # SSL
          ssl_certificate /etc/nginx/ssl/example.com_ecc/fullchain.cer;
          ssl_certificate_key /etc/nginx/ssl/example.com_ecc/example.com.key;
      
      
          # security headers
          include /etc/nginx/conf.d/security.conf;
      
          # reverse proxy
          location / {
              proxy_pass http://vaultwarden;
              proxy_http_version    1.1;
              proxy_cache_bypass    $http_upgrade;
              proxy_set_header Upgrade                      $http_upgrade;
              proxy_set_header Connection           "upgrade";
              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 X-Forwarded-Host     $host;
              proxy_set_header X-Forwarded-Port     $server_port;
          }
      
          # websocket 使用
          location /notifications/hub/negotiate {
      
              proxy_http_version 1.1;
              proxy_set_header "Connection" "";
      
              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_pass http://vaultwarden;
          }
      
          # websocket 使用
          location /notifications/hub {
              proxy_http_version 1.1;
              proxy_set_header Upgrade $http_upgrade;
              proxy_set_header Connection "upgrade";
      
              proxy_set_header Host $host;
              proxy_set_header X-Real-IP $remote_addr;
              proxy_set_header Forwarded $remote_addr;
              proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
              proxy_set_header X-Forwarded-Proto $scheme;
      
              proxy_pass http://vaultwarden:3012;
          }
      
          # gzip
          gzip on;
          gzip_vary on;
          gzip_proxied any;
          gzip_comp_level 6;
          gzip_types text/plain text/css text/xml application/json application/javascript application/rss+xml application/atom+xml image/svg+xml;
      }
      
    • jellyfin
      新建文件touch /home/admin/docker-data/nginx/sites-enabled/jellyfin.conf,并添加以下内容
      server {
          listen [::]:443 ssl;
          server_name jellyfin.example.com;
      
          # SSL
          ssl_certificate /etc/nginx/ssl/example.com_ecc/fullchain.cer;
          ssl_certificate_key /etc/nginx/ssl/example.com_ecc/example.com.key;
      
          # security headers
          include /etc/nginx/conf.d/security.conf;
      
          # reverse proxy
          location / {
              proxy_pass http://jellyfin:8096;
              proxy_set_header Host                         $host;
              proxy_set_header X-Real-IP                    $remote_addr;
              proxy_set_header X-Forwarded-For      $proxy_add_x_forwarded_for;
          }
      }
      
    • qbittorrent
      新建文件touch /home/admin/docker-data/nginx/sites-enabled/qbittorrent.conf,并添加以下内容
      server {
          listen [::]:443 ssl;
          server_name qbittorrent.example.com;
      
          # SSL
          ssl_certificate /etc/nginx/ssl/example.com_ecc/fullchain.cer;
          ssl_certificate_key /etc/nginx/ssl/example.com_ecc/example.com.key;
      
          # reverse proxy
          location / {
              proxy_pass http://qbittorrent: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;
          }
      }
      
    • samba
      新建文件夹mkdir /home/admin/docker-data/nginx/stream
      新建文件touch /home/admin/docker-data/nginx/stream/samba.conf,并添加以下内容
      server {
            listen 445;
            proxy_pass samba:445;
      }
      
  • 应用配置 所有配置文件都创建完成,执行 nginx exec -it nginx nginx -s reload 重载 nginx 配置,没有报错即可通过应用对应的地址访问。

总结

本篇主要部署应用,部分应用没有深入解释,如果可以,后续可以专门展开讲。因为很多配置都是相对应的,因此读者在试图修改配置时,应注意都哪些地方有依赖,需要全部都修改完成,特别是应用访问的配置,都是跟nginx息息相关的。