Mac 部署 NextCloud

准备

创建文件目录结构

1
2
3
4
5
mkdir nextcloud-onlyoffice
cd nextcloud-onlyoffice
touch docker-compose.yml
touch nginx.conf
mkdir rabbitmq_data

最终目录结构

1
2
3
4
5
6
7
nextcloud-onlyoffice/
├── docker-compose.yml
├── nginx.conf
└── rabbitmq_data/
    ├── mnesia/
    ├── schemas/
    └── ... (RabbitMQ自动生成的其他目录)

文件存储结构示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
_data/
├── admin/                  # 用户目录
│   ├── cache/              # 缓存文件
│   ├── files/              # 用户上传的文件
│   │   ├── Documents/      # 文档文件夹
│   │   ├── Photos/         # 照片文件夹
│   │   └── ...             # 其他文件
│   ├── files_trashbin/     # 回收站文件
│   └── ...                 # 其他用户数据
├── appdata_*/              # 应用数据
├── files_external/         # 外部存储挂载点
└── nextcloud.log           # NextCloud 日志

docker-compose.yml 和 nginx.conf

内网使用

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
version: '3'
services:
  app:
    container_name: app-server
    image: nextcloud:fpm
    stdin_open: true
    tty: true
    restart: always
    expose:
      - '80'
      - '9000'
    networks:
      - onlyoffice
    volumes:
      - app_data:/var/www/html
    environment:
      - TRUSTED_DOMAINS=localhost,app-server,主机IP,nginx-server    # 自己电脑的主机IP
      - OVERWRITEHOST=主机IP:2380                                   # 自己电脑的主机IP
      - OVERWRITEPROTOCOL=http

  onlyoffice-document-server:
    container_name: onlyoffice-document-server
    image: onlyoffice/documentserver:latest
    stdin_open: true
    tty: true
    restart: always
    networks:
      - onlyoffice
    expose:
      - '80'
      - '443'
    volumes:
      - document_data:/var/www/onlyoffice/Data
      - document_log:/var/log/onlyoffice
    ports:
      - 2280:80
      - 4423:443
    environment:
      - JWT_ENABLED=true        # 此处:是否打开秘钥认证
      - JWT_SECRET=root123456   # 此处:是onlyoffice的秘钥
      - AMQP_URI=amqp://guest:guest@rabbitmq
    depends_on:
      - rabbitmq

  nginx:
    container_name: nginx-server
    image: nginx
    stdin_open: true
    tty: true
    restart: always
    ports:
      - 2380:80
      - 4433:443
    networks:
      - onlyoffice
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
      - app_data:/var/www/html

  db:
    container_name: mariadb
    image: mariadb
    restart: always
    volumes:
      - mysql_data:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=Mysql123    # 此处:初始化数据库信息
      - MYSQL_PASSWORD=Msql123          # 此处:初始化数据库信息
      - MYSQL_DATABASE=nextcloud        # 此处:初始化数据库信息
      - MYSQL_USER=nextcloud            # 此处:初始化数据库信息
    networks:
      - onlyoffice

  rabbitmq:
    image: rabbitmq:3-management
    container_name: rabbitmq
    networks:
      - onlyoffice
    volumes:
      - rabbitmq_data:/var/lib/rabbitmq

networks:
  onlyoffice:
    driver: 'bridge'

volumes:
  document_data:
  document_log:
  app_data:
  mysql_data:
  rabbitmq_data:
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
user  www-data;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {

    upstream backend {
      server app-server:9000;
    }

    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    map $http_host $this_host {
        "" $host;
        default $http_host;
    }

    map $http_x_forwarded_proto $the_scheme {
        default $http_x_forwarded_proto;
        "" $scheme;
    }

    map $http_x_forwarded_host $the_host {
       default $http_x_forwarded_host;
       "" $this_host;
    }

    server {
        listen 80;

        # Add headers to serve security related headers
        add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;";
        add_header X-Content-Type-Options nosniff;
        add_header X-XSS-Protection "1; mode=block";
        add_header X-Robots-Tag none;
        add_header X-Download-Options noopen;
        add_header X-Permitted-Cross-Domain-Policies none;

        root /var/www/html;
        client_max_body_size 10G; # 0=unlimited - set max upload size
        fastcgi_buffers 64 4K;

        gzip off;

        index index.php;
        error_page 403 /core/templates/403.php;
        error_page 404 /core/templates/404.php;

        rewrite ^/.well-known/carddav /remote.php/dav/ permanent;
        rewrite ^/.well-known/caldav /remote.php/dav/ permanent;

        location = /robots.txt {
            allow all;
            log_not_found off;
            access_log off;
        }

        location ~ ^/(build|tests|config|lib|3rdparty|templates|data)/ {
            deny all;
        }

        location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) {
            deny all;
        }

        location / {
            rewrite ^/remote/(.*) /remote.php last;
            rewrite ^(/core/doc/[^\/]+/)$ $1/index.html;
            try_files $uri $uri/ =404;
        }

        location ~* ^/ds-vpath/ {
            rewrite /ds-vpath/(.*) /$1  break;
            proxy_pass http://onlyoffice-document-server;
            proxy_redirect     off;

            client_max_body_size 100m;

            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 X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Host $the_host;
            proxy_set_header X-Forwarded-Proto $the_scheme;
        }

        location ~ \.php(?:$|/) {
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
            include fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_param PATH_INFO $fastcgi_path_info;
            fastcgi_param HTTPS off;
            fastcgi_param modHeadersAvailable true; #Avoid sending the security headers twice
            fastcgi_pass backend;
            fastcgi_intercept_errors on;
        }

        # Adding the cache control header for js and css files
        location ~* \.(?:css|js)$ {
            add_header Cache-Control "public, max-age=7200";
            # Add headers to serve security related headers
            add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;";
            add_header X-Content-Type-Options nosniff;
            add_header X-Frame-Options "SAMEORIGIN";
            add_header X-XSS-Protection "1; mode=block";
            add_header X-Robots-Tag none;
            add_header X-Download-Options noopen;
            add_header X-Permitted-Cross-Domain-Policies none;
            access_log off;
        }

        location ~* \.(?:jpg|jpeg|gif|bmp|ico|png|swf)$ {
            access_log off;
        }
    }
}

外网使用

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
version: '3'
services:
  app:
    container_name: app-server
    image: nextcloud:fpm
    stdin_open: true
    tty: true
    restart: always
    expose:
      - '80'
      - '9000'
    networks:
      - onlyoffice
    volumes:
      - app_data:/var/www/html
    environment:
      - TRUSTED_DOMAINS=localhost,app-server,本机IP,nginx-server,域名   # 主机IP、域名
      - OVERWRITEHOST=域名                                              # 域名
      - OVERWRITEPROTOCOL=http
      - OVERWRITECLIURL=http://域名                                     # 域名

  onlyoffice-document-server:
    container_name: onlyoffice-document-server
    image: onlyoffice/documentserver:latest
    stdin_open: true
    tty: true
    restart: always
    networks:
      - onlyoffice
    expose:
      - '80'
      - '443'
    volumes:
      - document_data:/var/www/onlyoffice/Data
      - document_log:/var/log/onlyoffice
    ports:
      - 2280:80
      - 4423:443
    environment:
      - JWT_ENABLED=true        # 此处:是否打开秘钥认证
      - JWT_SECRET=root123456   # 此处:是onlyoffice的秘钥
      - AMQP_URI=amqp://guest:guest@rabbitmq
    depends_on:
      - rabbitmq

  nginx:
    container_name: nginx-server
    image: nginx
    stdin_open: true
    tty: true
    restart: always
    ports:
      - 2380:80
      - 4433:443
    networks:
      - onlyoffice
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
      - app_data:/var/www/html

  db:
    container_name: mariadb
    image: mariadb
    restart: always
    volumes:
      - mysql_data:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=Mysql123    # 此处:初始化数据库信息
      - MYSQL_PASSWORD=Msql123          # 此处:初始化数据库信息
      - MYSQL_DATABASE=nextcloud        # 此处:初始化数据库信息
      - MYSQL_USER=nextcloud            # 此处:初始化数据库信息
    networks:
      - onlyoffice

  rabbitmq:
    image: rabbitmq:3-management
    container_name: rabbitmq
    networks:
      - onlyoffice
    volumes:
      - rabbitmq_data:/var/lib/rabbitmq

networks:
  onlyoffice:
    driver: 'bridge'

volumes:
  document_data:
  document_log:
  app_data:
  mysql_data:
  rabbitmq_data:
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
user www-data;
worker_processes auto;

error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
    worker_connections 1024;
}

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    
    # 添加 MJS 类型支持
    types {
        text/javascript mjs;
        application/javascript mjs;
    }

    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                   '$status $body_bytes_sent "$http_referer" '
                   '"$http_user_agent" "$http_x_forwarded_for"';

    access_log /var/log/nginx/access.log main;

    sendfile on;
    keepalive_timeout 65;
    client_max_body_size 10G;

    map $http_host $this_host {
        "" $host;
        default $http_host;
    }

    map $http_x_forwarded_proto $the_scheme {
        default $http_x_forwarded_proto;
        "" $scheme;
    }

    map $http_x_forwarded_host $the_host {
        default $http_x_forwarded_host;
        "" $this_host;
    }

    upstream backend {
        server app-server:9000;
    }

    server {
        listen 80;
        server_name 域名;   # 域名
        
        # 修复安全头设置
        add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;" always;
        add_header X-Content-Type-Options nosniff always;
        add_header X-XSS-Protection "1; mode=block" always;
        add_header X-Robots-Tag "noindex, nofollow" always;
        add_header X-Download-Options noopen always;
        add_header X-Permitted-Cross-Domain-Policies none always;
        add_header Referrer-Policy "no-referrer" always;
        add_header X-Frame-Options "SAMEORIGIN" always;

        root /var/www/html;
        fastcgi_buffers 64 4K;
        gzip off;

        index index.php;
        error_page 403 /core/templates/403.php;
        error_page 404 /core/templates/404.php;

        # 修复 .well-known 路由
        location ^~ /.well-known {
            location /.well-known/carddav { return 301 /remote.php/dav/; }
            location /.well-known/caldav  { return 301 /remote.php/dav/; }
            location /.well-known/webfinger { return 301 /index.php$uri; }
            location /.well-known/nodeinfo { return 301 /index.php$uri; }
            return 301 /index.php$request_uri;
        }

        # 修复 ocm-provider 路由
        location = /ocm-provider {
            return 301 /index.php$request_uri;
        }

        location / {
            rewrite ^/remote/(.*) /remote.php last;
            rewrite ^(/core/doc/[^\/]+/)$ $1/index.html;
            try_files $uri $uri/ /index.php$uri?$args;
        }

        location ~ ^/(build|tests|config|lib|3rdparty|templates|data)/ {
            deny all;
        }

        location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) {
            deny all;
        }

        location ~ \.php(?:$|/) {
            fastcgi_split_path_info ^(.+?\.php)(/.*)$;
            include fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_param PATH_INFO $fastcgi_path_info;
            fastcgi_param HTTPS off;
            fastcgi_param modHeadersAvailable true;
            fastcgi_pass backend;
            fastcgi_intercept_errors on;
        }

        # OnlyOffice 代理设置
        location ~* ^/ds-vpath/ {
            rewrite /ds-vpath/(.*) /$1 break;
            proxy_pass http://onlyoffice-document-server;
            proxy_redirect off;
            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 X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Host $the_host;
            proxy_set_header X-Forwarded-Proto $the_scheme;
        }

        # 静态资源缓存
        location ~* \.(?:css|js|mjs)$ {
            add_header Cache-Control "public, max-age=7200" always;
            access_log off;
        }

        location ~* \.(?:jpg|jpeg|gif|bmp|ico|png|swf)$ {
            access_log off;
        }
    }
}

cpolar 内网穿透

/images/documents/Mac部署NextCloud/1.png
(图1)
/images/documents/Mac部署NextCloud/2.png
(图2)
1
2
# 启动命令
cplar http 2380 -hostname=域名

启动

1
docker-compose up -d

等待所有容器启动后(约2-3分钟),配置 NextCloud

  • 访问 http://IP:2380
  • 创建管理员账户
  • 安装完成后,进入 头像 → 应用 → Files → 搜索 OnlyOffice → 安装启用
  • 启用后,进入 头像 → 个人设置 → ONLYOFFICE
  • 文档服务器地址填写:http://IP:2280
  • 密钥填写:root123456
  • 保存设置
/images/documents/Mac部署NextCloud/6.png
(图6)
/images/documents/Mac部署NextCloud/3.png
(图3)
/images/documents/Mac部署NextCloud/4.png
(图4)
/images/documents/Mac部署NextCloud/5.png
(图5)

0%