Introducción
Podríamos decir que este articulo es una extensión del anterior que he escrito. Una suma de experiencia acumulada gracias a ideas que han venido pasando por mi mente y que probablemente sirva como idea para algo posterior. En este caso, tras aprender a configurar WireGuard, noté que daba mas ventajas que usar un tunel inverso, así que empece a trastear al darme cuenta que Nginx no sirve solo de proxy inverso para servicios locales, sino también, para otros al alcance de su red.El problema
No sabría decir si es un problema. Yo solo quería tener nextcloud y todos sus beneficios, pero mis recursos limitados me dejaban con un pobre VPS con un procesador de 1 nucleo, 1GB de ram y 25GB de disco duro, recursos que se acabaron rápidamente a pesar de ser el unico usuario. Al darme cuenta que tengo un LarkBox X 2023-Mini de Chuwi funcionando 24/7 para unos experimentos, me di cuenta que tal vez, lo mejor, seria usarlo de forma local. Pero entonces tendria que perder funciones que me sirven, como el gestor de marcadores flocus o mi bot de icsannouncer o el cliente de correo electrónico (no, no uso el roundcube que dijeron iban a unir a nextcloud) y claro, la funcion de compartir archivos públicamente. La cosa va de que con 1GB no se puede hacer mucho. Solo el servicio de MariaDB consume la mitad de la memoria que hay y se necesita tener activo, como mínimo, los servicios de Nginx, MariaDB, PHP-fpm, fail2ban, SSH y bueno, syncthing que lo tengo por si las dudas. Es también un problema el hecho de que los bots de ia, crawlers y otros esten jode que jode, minando los escasos megas que tiene mi VPS, asi que a cada rato se muere, principalmente, MariaDB, poniendo en riesgo la integridad de la base de datos.La Solución
En principio pensé que podría aprovechar el túnel inverso que creé y usaba para acceder al terminal del Larkbox. Pero era lento. Y habia que crear un tunel por cada servicio y para coronar, se desconectaba en cada salto de red, por lo que tendría que volver a casa a revivirlo. Esto ultimo lo resolví usando autossh pero igual es un fastidio. Tras conocer WireGuard (lo conocía de hace mucho pero nunca le di importancia) me di cuenta de que no necesitaba usarlo como VPN en el sentido de acceder a paginas restringidas mediante mi server, sino como VPN en el sentido de Red Privada Virtual. Es decir, para acceder mediante internet a mi red domestica y por supuesto, acceder a sus servicios. Queda pendiente escribir sobre el experimento de utilizar Moonlight mediante WireGuard, Pero al notar que se podía levantar el servicio y no necesitar prestarle mayor atención, pensé que podría aprovecharlo para aprovechar NextCloud mediante la VPN. Esto me daba solución a casi todos los problemas que tenia, excepto, la compartición de archivos públicos. Queda pendiente escribir sobre muchas cosas que me di cuenta con este experimento. En realidad se puede hacer mas de lo que haremos en este articulo y me sorprendí. Podría reducir gastos de esta manera y por un instante pensé que incluso podría ahorrarme la factura de la luz mediante paneles solares, pero vamos por partes.🌟El tutorial🌟
Advertencia. Este tutorial asume que ya tienes instalado y respaldado Nextcloud, WireGuard, Nginx, PHP-FPM y todos los módulos necesarios para que funcione NextCloud .Debido a que esto es básicamente una migración de un servidor a otro, estoy asumiendo que conoces la mayoría de los pasos descritos en la cita. Ademas ya hay un montón de tutoriales para cada cosa y no quiero ser redundante. WireGuard en cambio, creo que escribiré un tutorial debido a ciertos problemas que me encontré y haré unas cuantas aclaraciones sobre Nginx. Hechas estas aclaraciones, al momento de leer este articulo ya deberías:
- Creado un archivo zip de tu servidor de origen de las carpetas
NextCloudynextcloud_data - Traído estas carpetas a tu nuevo servidor
- Descomprimido los archivos en sus respectivos directorios
- Asegurado que los archivos tengan los permisos y propiedades necesarios
- Creado el tunel entre tu VPS y tu equipo domestico (si, puede ser tu celular si tienes paciencia suficiente)
- Tener VPS :v
- Tener dominio :v
- Tener certificados SSL XD (afortunadamente solo necesitas uno y si como yo, estas migrando desde un servidor ya creado, puedes reaprovechar ese)
sites-avaliable y sites-enabled. En el Nginx del propio sitio utilizan un modelo único de archivos *.conf dentro de la carpeta conf.d. Te recomiendo este ultimo porque da ciertas ventajas, como disponer de HTTP2 y HTTP3 y mayor seguridad, aparte de estar mas actualizado
Lo mismo aplica a MariaDB. Te recomiendo los paquetes oficiales, aunque probablemente te encuentres con un error en Nextcloud que puedes ignorar.
Versión de base de datos Se detectó la versión «12.2.1-MariaDB-ubu2404» de MariaDB. Se sugiere utilizar una versión de MariaDB entre >=10.6 y <=11.8 para un mejor rendimiento, estabilidad y funcionalidad con esta versión de Nextcloud.¿Dando tanto por sentado esto todavía califica como tutorial? WireGuard permite crear una Red Privada Virtual, en la que cada dispositivo que se una, puede ver a los demás en lo que se conoce como una red Mesh. Por supuesto, esto es en forma virtual, porque fuera de tu red VPN sigues usando el modelo Cliente/Servidor (Estrella), puesto que si el servidor se desconecta, nadie mas puede usar la VPN Arquitecturas de red punto a punto, estrella y mesh Debido a esta arquitectura de red, es posible que cualquier miembro de la red ofrezca servicios y los demás consuman de ellos. Esto incluye al servidor, que puede actuar de cliente para consumir lo que sirva otro miembro de la red VPN. Gracias a esto, podemos permitir al servidor, mediante Nginx, los servicios que ofrezca uno de los clientes. Puede ser cualquiera. Hay que tener en cuenta que este modelo de servidor no es el apropiado para producción, como tampoco lo era el tunel inverso, pero para uso personal, esta muy bien.
Configuración local
Primero, configura Nginx en el equipo local para servir Nextcloud. Te sugiero este modelo de archivo de configuración que me ha servido para este propósito. Por supuesto, puedes servirlo en el puerto 80 como es común para http no seguro, o en cualquier puerto que desees, ajústalo en el archivo de configuración1 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 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
map $arg_v $asset_immutable { "" ""; default "immutable"; } server { server_name tuserverpublico.com; server_tokens off; access_log /var/log/nginx/nextcloud.tuserverpublico.com.access.log; error_log /var/log/nginx/nextcloud.tuserverpublico.com.error.log; root /var/www/nextcloud; client_max_body_size 512M; client_body_timeout 300s; fastcgi_buffers 64 4K; # Enable gzip but do not remove ETag headers gzip on; gzip_vary on; gzip_comp_level 4; gzip_min_length 256; gzip_proxied expired no-cache no-store private no_last_modified no_etag auth; gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/wasm application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy; # Pagespeed is not supported by Nextcloud, so if your server is built # with the `ngx_pagespeed` module, uncomment this line to disable it. #pagespeed off; # The settings allows you to optimize the HTTP2 bandwitdth. # See https://blog.cloudflare.com/delivering-http-2-upload-speed-improvements/ # for tunning hints client_body_buffer_size 512k; # HTTP response headers borrowed from Nextcloud `.htaccess` add_header Referrer-Policy "no-referrer" always; add_header X-Content-Type-Options "nosniff" always; add_header X-Download-Options "noopen" always; add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Permitted-Cross-Domain-Policies "none" always; add_header X-Robots-Tag "noindex,nofollow" always; add_header X-XSS-Protection "1; mode=block" always; add_header Strict-Transport-Security "max-age=15768000;includeSubDomains;preload;" always; # Remove X-Powered-By, which is an information leak fastcgi_hide_header X-Powered-By; # Specify how to handle directories -- specifying `/index.php$request_uri` # here as the fallback means that Nginx always exhibits the desired behaviour # when a client requests a path that corresponds to a directory that exists # on the server. In particular, if that directory contains an index.php file, # that file is correctly served; if it doesn't, then the request is passed to # the front-end controller. This consistent behaviour means that we don't need # to specify custom rules for certain paths (e.g. images and other assets, # `/updater`, `/ocm-provider`, `/ocs-provider`), and thus # `try_files $uri $uri/ /index.php$request_uri` # always provides the desired behaviour. include mime.types; types { text/javascript mjs; } # Rules borrowed from `.htaccess` to hide certain paths from clients location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/) { return 404; } location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) { return 404; } index index.php index.html /index.php$request_uri; location ~ \.php(?:$|/) { #try_files $uri =404; #try_files $uri $uri/ /index.php?$args; rewrite ^/(?!index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+|.+\/richdocumentscode\/proxy) /index.php$request_uri; fastcgi_split_path_info ^(.+?\.php)(/.*)$; try_files $fastcgi_script_name =404; set $path_info $fastcgi_path_info; #fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; #include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php8.3-fpm.sock; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $path_info; fastcgi_param HTTPS on; fastcgi_param modHeadersAvailable true; # Avoid sending the security headers twice fastcgi_param front_controller_active true; # Enable pretty urls #fastcgi_pass php-handler; fastcgi_intercept_errors on; fastcgi_request_buffering off; fastcgi_max_temp_file_size 0; #autoindex on; } location ~ \.(?:css|js|mjs|svg|gif|ico|jpg|png|webp|wasm|tflite|map|ogg|flac)$ { try_files $uri /index.php$request_uri; # HTTP response headers borrowed from Nextcloud `.htaccess` add_header Cache-Control "public, max-age=15778463$asset_immutable"; add_header Referrer-Policy "no-referrer" always; add_header X-Content-Type-Options "nosniff" always; add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Permitted-Cross-Domain-Policies "none" always; add_header X-Robots-Tag "noindex, nofollow" always; add_header X-XSS-Protection "1; mode=block" always; access_log off; # Optional: Don't log access to assets } location ~ \.(otf|woff2?)$ { try_files $uri /index.php$request_uri; expires 7d; # Cache-Control policy borrowed from `.htaccess` access_log off; # Optional: Don't log access to assets } # Rule borrowed from `.htaccess` location /remote { return 301 /remote.php$request_uri; } location / { try_files $uri $uri/ /index.php$request_uri; #autoindex on; } location = / { if ( $http_user_agent ~ ^DavClnt ) { return 302 /remote.php/webdav/$is_args$args; } } #location ~ /\.ht { # deny all; #} location = /robots.txt { allow all; log_not_found off; access_log off; } 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; location /.well-known/nodeinfo { default_type application/json; return 404 '{"message": "nodeinfo not supported"}'; add_header x-nextcloud-well-known 1 always; } location /.well-known/webfinger { default_type application/json; return 404 '{"message": "webfinger not supported"}'; add_header x-nextcloud-well-known 1 always; } } listen 80; }Recuerda reemplazar
tuserverpublico.com por el nombre de dominio de tu VPS que recibira el trafico externo y usar el socket de tu instancia de PHP-fpm. En mi caso utilicé fastcgi_pass unix:/run/php/php8.3-fpm.sock; porque es lo que uso.
Necesitas ahora agregar al array de configuracion de tu instancia de nextcloud, las siguientes lineas
<?php$CONFIG = array ( ... 'trusted_proxies' => ['ip_wireguard_del_servidor '], 'overwrite.cli.url' => 'https://tuservidorpublico.com', 'overwritehost' => 'tuservidorpublico.com', 'overwriteprotocol' => 'https', 'datadirectory' => '/var/www/nextcloud_data', 'overwriteprotocol' => 'https', 'overwrite.cli.url' => 'https://tuservidorpublico.com', ... );la ip_wireguard_del_servidor es la ip que tiene asignada el servidor publico en la red de WireGuard. recuerda confirmar que este activo overwriteprotocol en https y overwritehost en tu direccion de dominio publica. Otra cosa mas. Es probable que quieras llevar la carpeta de nextcloud_data a otro disco o directorio, pero las politicas de seguridad impiden que hagas esto. Te ahorro sufrimiento diciendotelo para que no pierdas tiempo intentando muchas cosas sin exito. Eso si, recuerda que nextcloud_data, no debe ser servida en publico, por lo que no debe estar dentro de la carpeta nextcloud ni tampoco en algun directorio que se encuentre siendo servido por nginx.
Configuracion del Servidor
Ya estamos en las configuraciones finales. En este caso puedes cambiar solo lo necesario para que tu servidor previo haga de proxy inverso para tu instancia local de NextCloud, pero te comparto las configuraciones necesarias tambien.map $arg_v $asset_immutable { "" ""; default "immutable"; } server { server_name tuservidorpublico.com; server_tokens off; access_log /var/log/nginx/tuservidorpublico.com.access.log; error_log /var/log/nginx/tuservidorpublico.com.error.log; location / { proxy_pass http://ip_wireguard_del_cliente ; 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-Proto $scheme; proxy_buffering off; proxy_request_buffering off; client_max_body_size 512M; proxy_cache_bypass $http_upgrade; } location ~ ^/(?:\.|autotest|occ|issue|indie|db_structure|console) { deny all; } listen 443 ssl http2; # managed by Certbot ssl_certificate /etc/letsencrypt/live/tuservidorpublico.com/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/tuservidorpublico.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 } server { if ($host = tuservidorpublico.com) { return 301 https://$host$request_uri; } # managed by Certbot server_name tuservidorpublico.com; listen 80; return 404; # managed by Certbot }Estas configuraciones son mas cortas, pero tengo algunas observaciones que hacer.
- proxy_pass http://ip_wireguard_del_cliente ; debes reemplazarla por la direccion ip que tiene el equipo local en la red WireGuard.
- Tanto en el equipo local como en el servidor, he segmentado los logs por dominio, para que sea mas facil de depurar.ç
- Las configuraciones SSL estan manejadas por el certbot. Genera las tuyas propias.
- listen 443 ssl http2; solo funciona en Nginx de los repositorios nativos de Debian/Ubuntu porque esta desactualizado.
Conclusiones
Con estas configuraciones y observaciones, ya deberías tener una instancia publica de NextCloud, utilizando WireGuard para un servidor local. Puedes servir cualquier otra cosa con esta estrategia pero recuerda tomar todas las medidas de precaución pertinentes pues internet es un lugar salvaje. Consumo de RAM desactivando servicios no necesitados después de mover NextCloud a servidor local Al momento de escribir este articulo, todo funciona bien y el consumo de CPU y RAM de mi servidor ha bajado muchisimo, llegando a consumir solo 205M de RAM de los 979M que dispongo. Por supuesto, si estas usando AWS u otro servicio en el que pagas por consumo, ten cuidado. Esto reduce el consumo de recursos de computo, pero no de red. Debido a que ahora hay mas vueltas, es posible que el consumo de red se duplique, porque el esquema es el siguiente:- El usuario pide un recurso al servidor publico (acceder a la portada, pedir un archivo, etc).
- El servidor pide este recurso al servidor local.
- WireGuard pide los recursos al servidor loca.
- El servidor local responde.
- WireGuard entrega los recursos al servidor publico.
- El servidor entrega los recursos al cliente.
- El usuario pide un recurso al servidor publico.
- El servidor publico entrega el recurso al usuario.


