Última revisión: 2 de octubre de 2021
- Versiones a instalar
- Configurando el Sistema Operativo
- Instalación de MariaDB
- Instalación de nginx
- Instalación de PHP
- Instalación de Redis
- Limpiando los sitios por defecto
- Instalación de WP-CLI
- Configuración de la red Tor
- Configuración de los servicios
- Creación de un sitio web
- Asegurando el .onion
- Sobre este documento
Este tutorial ha sido creado en un VPS de Clouding.io. Puedes crear tu propio VPS desde 3€/mes.
Además, tienes la posibilidad de crear tu VPS con la imagen de WordPress en un clic.
COLABORACIÓN
Versiones a instalar
Sistema Operativo: Ubuntu 20
Panel de Control: ninguno
Servidor web: nginx
Base de Datos: MariaDB 10.5
Procesador: PHP 8.0
Caché: Redis
recuerda que si vas a montar el sistema, tanto en local como en un sitio externo, deberás dejar el puerto 9050 disponible (y si quieres control externo, el 9051) para que puedan abrirse los sockets necesarios de la red Tor. Además, el puerto 80 para las conexiones web.
Configurando el Sistema Operativo
Una vez esté instalado el sistema operativo, lo primero que configuraremos será la hora del servidor. En este caso configuraremos la zona horaria universal UTC.
timedatectl set-timezone 'UTC'
timedatectl set-ntp onLo siguiente que haremos es comprobar la versión del sistema operativo y, posteriormente, hacer una actualización completa del mismo.
lsb_release -a
apt -y update && apt -y upgrade && apt -y dist-upgrade && apt -y autoremoveUna vez esta todo actualizado, instalamos algunas herramientas y software base que puede ser útil tener en el sistema.
apt -y install software-properties-common curl vim zip unzip apt-transport-httpsInstalación de MariaDB
El siguiente paso será la instalación de la base de datos. En este caso vamos a utilizar MariaDB 10.5. Lo primero que haremos será configurar la descarga, y posteriormente su instalación.
curl -sS https://downloads.mariadb.com/MariaDB/mariadb_repo_setup | sudo bash -s -- --mariadb-server-version="mariadb-10.5"
apt -y update && apt -y upgrade && apt -y dist-upgrade && apt -y autoremove
apt -y install mariadb-server mariadb-clientAhora que está instalada, procederemos a la configuración inicial. Para ello usaremos el sistema se instalación segura, que nos hará algunas preguntas.
mysql_secure_installationA la pregunta de si queremos cambiar la contraseña, dependiendo de si hemos puesto o no en la instalación, la cambiaremos. En caso de no haber puesto ninguna, es muy recomendable ponerle una contraseña segura.
Set root password? [Y/n]: YAl resto de preguntas, contestaremos lo siguiente:
Remove anonymous users? [Y/n]: Y
Disallow root login remotely? [Y/n]: Y
Remove test database and access to it? [Y/n]: Y
Reload privilege tables now? [Y/n]: YEn este momento ya tendremos la base de datos configurada. Ahora haremos que se ejecute en los re inicios del sistema y la iniciaremos.
systemctl stop mysql.service
systemctl enable mysql.service
systemctl start mysql.service
systemctl status mysql.serviceInstalación de nginx
A partir de aquí tenemos la base de datos configurada y vamos a proceder a la instalación del servidor web. En este caso vamos a usar nginx. Para estar al día, no usaremos la versión que viene con el sistema operativo, sino una más actualizada y mantenida.
add-apt-repository ppa:ondrej/nginx
apt -y update && apt -y upgrade && apt -y dist-upgrade && apt -y autoremove
apt -y install nginx nginx-extrasAhora que tenemos nginx instalado, lo vamos a configurar para que se inicie en los re inicios del sistema automáticamente.
systemctl stop nginx.service
systemctl enable nginx.service
systemctl start nginx.service
systemctl status nginx.serviceInstalación de PHP
En este momento ya tenemos el servidor web, por lo que vamos a instalar y a configurar PHP para que funcione correctamente con la base de datos y el servidor web. En este caso vamos a instalar la versión PHP 8.0. Primero haremos la instalación de los paquetes más actualizados (que no son los que vienen con el sistema operativo) y que en caso de necesitarlo, además, nos permitirían tener varias versiones de PHP en paralelo.
add-apt-repository ppa:ondrej/php
apt -y update && apt -y upgrade && apt -y dist-upgrade && apt -y autoremove
apt -y install php8.0 php8.0-fpm php8.0-common php8.0-dev php8.0-cli php8.0-bcmath php8.0-curl php8.0-gd php8.0-imap php8.0-mbstring php8.0-mysql php8.0-opcache php8.0-soap php8.0-xml php8.0-zip php8.0-xdebug libgeoip-dev php-pear pkg-config imagemagick libmagickwand-dev php8.0-imagickAhora que ya tenemos PHP correctamente instalado, vamos a activarlo de forma que cuando se reinicie el sistema se ejecute automáticamente.
systemctl stop php8.0-fpm.service
systemctl enable php8.0-fpm.service
systemctl start php8.0-fpm.service
systemctl status php8.0-fpm.service
php -vTambién aprovecharemos en actualizar el PECL.
pecl channel-update pecl.php.netInstalación de Redis
Para trabajar con unas mejoras en el rendimiento de la caché de objetos, vamos a dejar listo Redis como sistema de almacenamiento.
apt -y update && apt -y upgrade && apt -y dist-upgrade && apt -y autoremove
apt -y install redis-server php8.0-redisPosteriormente, y de la misma forma que el resto de elementos, lo vamos a configurar para que se inicie automáticamente si se reinicia el servidor.
systemctl stop redis-server.service
systemctl enable redis-server.service
systemctl start redis-server.service
systemctl status redis-server.serviceLimpiando los sitios por defecto
Por defecto, el sistema responde a la dirección IP y a otros elementos. Para evitar que los sitios por defecto se muestren, eliminaremos las páginas por defecto.
Eliminamos todos los ficheros por defecto.
rm /var/www/html/index.*Y crearemos la página por defecto.
vim /var/www/html/index.htmlDonde añadiremos el contenido de la página por defecto.
<!DOCTYPE html>
<p>Hello World!</p>Y crearemos un fichero de robots.txt para que no se indexen estas páginas por defecto.
vim /var/www/html/robots.txtDonde añadiremos el contenido del fichero que impida la indexación.
User-Agent: *
Disallow: /Instalación de WP-CLI
Para la creación de nuestros sitios WordPress, usaremos la instalación mediante WP-CLI.
cd /root/
curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
php wp-cli.phar --info
chown www-data: wp-cli.phar
chmod +x wp-cli.phar
mv wp-cli.phar /usr/local/bin/wpY validamos que esté instalado y actualizado.
wp --info
wp cli updateConfiguración de la red Tor
Desde Ubuntu es muy sencillo configurar la red de Tor ya que sólo hemos de instalarla (no requiere de ninguna configuración extra).
apt -y install tor
apt -y update && apt -y upgrade && apt -y dist-upgrade && apt -y autoremoveUna vez se haya realizado la instalación, podemos sustituir el fichero de configuración por defecto de Tor con el que indicamos a continuación. Hay que tener en cuenta que por defecto Tor viene «sin configuración», por lo que principalmente es activar y adaptar lo que no viene por defecto.
SocksPort 9050
RunAsDaemon 1
DataDirectory /var/lib/tor
HiddenServiceDir /var/lib/tor/site_1/
HiddenServicePort 80 127.0.0.1:80
#HiddenServiceDir /var/lib/tor/site_2/
#HiddenServicePort 80 127.0.0.1:80Ahora que hemos configurado todo, crearemos las carpetas donde se almacenarán los datos y le daremos los permisos correspondientes.
mkdir /var/lib/tor/site_1/
chmod 700 /var/lib/tor/site_1/
chown -R debian-tor:debian-tor /var/lib/tor/site_1/Ya tenemos la configuración de Tor, por lo que vamos a reiniciar el servicio para validr
service tor@default stop
service tor@default start
service tor@default statusCon esto veremos que Tor ya está activo y funcionando en el servidor. Ahora queda configurar la web para que sea visible a los usuarios de la red.
Antes de continuar, podremos ya saber el nombre de dominio (.onion) que se nos ha asignado.
cat /var/lib/tor/site_1/hostnameEsto nos devolverá un dominio / sitio del estilo a:
zmtbc6ql65tzrgpqfq22wo4easzevuhwpg35ztn4kzkyreabdbbbnpad.onionConfiguración de los servicios
Configuración de nginx
Haremos unas copias de seguridad de los ficheros de configuración de sitios para posteriormente poner los nuestros.
cd /etc/nginx/sites-enabled/
rm default
cd /etc/nginx/sites-available/
rm defaultConfiguraremos la configuración global de nginx.
cd /etc/nginx/
vim nginx.confCon el siguiente contenido:
user www-data;
pid /run/nginx.pid;
worker_processes auto;
worker_rlimit_nofile 65535;
include /etc/nginx/modules-enabled/*.conf;
events {
multi_accept on;
worker_connections 65535;
use epoll;
}
http {
charset utf-8;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
server_tokens off;
more_clear_headers Server;
log_not_found off;
types_hash_max_size 2048;
client_max_body_size 64m;
keepalive_timeout 10;
server_names_hash_bucket_size 128;
server_names_hash_max_size 1024;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# logging
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
# TLS
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
# gzip
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 9;
gzip_disable "msie6";
gzip_buffers 16 8k;
gzip_min_length 1100;
gzip_types application/atom+xml application/javascript application/json application/x-javascript application/xml application/xml+rss image/svg+xml text/css text/javascript text/plain text/xml;
# more
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}Y configuramos las opciones de PHP 8 para WordPress.
cd /etc/nginx/
vim wordpress_fastcgi_8_0.confCon el siguiente contenido:
fastcgi_pass unix:/var/run/php/php8.0-fpm.sock;
fastcgi_index index.php;
fastcgi_buffers 256 16k;
fastcgi_buffer_size 128k;
fastcgi_busy_buffers_size 256k;
fastcgi_temp_file_write_size 256k;
fastcgi_hide_header X-Powered-By;
fastcgi_hide_header X-Pingback;
fastcgi_hide_header Link;
fastcgi_intercept_errors off;
fastcgi_split_path_info ^(.+.php)(/.+)$;
try_files $fastcgi_script_name =404;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PHP_ADMIN_VALUE open_basedir=$document_root/:/usr/lib/php/:/tmp/;
fastcgi_param PATH_INFO $path_info;
set $path_info $fastcgi_path_info;
include fastcgi.conf;Probamos y reiniciamos nginx.
nginx -t
nginx -s reloadConfiguración de PHP 8
Hacemos una copia de seguridad de la configuración de PHP para crear la nuestra propia.
cd /etc/php/8.0/fpm/
cp php.ini php.ini.original
vim /etc/php/8.0/fpm/php.iniCon el siguiente contenido:
[PHP]
engine = On
short_open_tag = Off
precision = 14
output_buffering = 4096
zlib.output_compression = Off
implicit_flush = Off
unserialize_callback_func =
serialize_precision = -1
disable_functions = pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
disable_classes =
zend.enable_gc = On
zend.exception_ignore_args = On
zend.exception_string_param_max_len = 0
expose_php = Off
max_execution_time = 60
max_input_time = 60
memory_limit = 256M
error_reporting = E_ALL
display_errors = Off
display_startup_errors = Off
log_errors = On
log_errors_max_len = 1024
ignore_repeated_errors = Off
ignore_repeated_source = Off
report_memleaks = On
html_errors = On
variables_order = "GPCS"
request_order = "GP"
register_argc_argv = Off
auto_globals_jit = On
post_max_size = 32M
auto_prepend_file =
auto_append_file =
default_mimetype = "text/html"
default_charset = "UTF-8"
doc_root =
user_dir =
enable_dl = Off
file_uploads = On
upload_max_filesize = 32M
max_file_uploads = 20
allow_url_fopen = On
allow_url_include = Off
default_socket_timeout = 60
[CLI Server]
cli_server.color = On
[Date]
date.timezone = 'UTC'
[Pdo_mysql]
pdo_mysql.cache_size = 2000
pdo_mysql.default_socket=
[mail function]
SMTP = localhost
smtp_port = 25
mail.add_x_header = Off
[ODBC]
odbc.allow_persistent = On
odbc.check_persistent = On
odbc.max_persistent = -1
odbc.max_links = -1
odbc.defaultlrl = 4096
odbc.defaultbinmode = 1
[MySQLi]
mysqli.max_persistent = -1
mysqli.allow_persistent = On
mysqli.max_links = -1
mysqli.cache_size = 2000
mysqli.default_port = 3306
mysqli.default_socket =
mysqli.default_host =
mysqli.default_user =
mysqli.default_pw =
mysqli.reconnect = Off
[mysqlnd]
mysqlnd.collect_statistics = On
mysqlnd.collect_memory_statistics = Off
[bcmath]
bcmath.scale = 0
[Session]
session.save_handler = files
session.use_strict_mode = 0
session.use_cookies = 1
session.use_only_cookies = 1
session.name = PHPSESSID
session.auto_start = 0
session.cookie_lifetime = 0
session.cookie_path = /
session.cookie_domain =
session.cookie_httponly =
session.serialize_handler = php
session.gc_probability = 0
session.gc_divisor = 1000
session.gc_maxlifetime = 1440
session.referer_check =
session.cache_limiter = nocache
session.cache_expire = 180
session.use_trans_sid = 0
session.sid_length = 26
session.trans_sid_tags = "a=href,area=href,frame=src,form="
session.sid_bits_per_character = 5
[Assertion]
zend.assertions = -1
[Tidy]
tidy.clean_output = Off
[soap]
soap.wsdl_cache_enabled=1
soap.wsdl_cache_dir="/tmp"
soap.wsdl_cache_ttl=86400
soap.wsdl_cache_limit = 5
[ldap]
ldap.max_links = -1
[opcache]
opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=10000
opcache.max_wasted_percentage=15
opcache.revalidate_freq=60
opcache.fast_shutdown=1
opcache.enable_cli=1Y reiniciamos PHP.
systemctl restart php8.0-fpm.service
systemctl status php8.0-fpm.serviceConfiguración de Redis
Hacemos una copia de los ficheros de configuración.
cd /etc/redis/
cp redis.conf redis.conf.original
vim /etc/redis/redis.confCon el siguiente contenido:
# include /path/to/local.conf
# include /path/to/other.conf
# loadmodule /path/to/my_module.so
# loadmodule /path/to/other_module.so
# bind 192.168.1.100 10.0.0.1
# bind 127.0.0.1 ::1
bind 127.0.0.1 ::1
protected-mode yes
port 6379
tcp-backlog 511
# unixsocket /var/run/redis/redis-server.sock
# unixsocketperm 700
timeout 0
tcp-keepalive 300
daemonize yes
supervised no
pidfile /var/run/redis/redis-server.pid
loglevel notice
logfile /var/log/redis/redis-server.log
# syslog-enabled no
# syslog-ident redis
# syslog-facility local0
databases 4
always-show-logo yes
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir /var/lib/redis
# slaveof
# masterauth
slave-serve-stale-data yes
slave-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5
# repl-ping-slave-period 10
# repl-timeout 60
repl-disable-tcp-nodelay no
# repl-backlog-size 1mb
# repl-backlog-ttl 3600
slave-priority 100
# min-slaves-to-write 3
# min-slaves-max-lag 10
# min-slaves-max-lag is set to 10.
# slave-announce-ip 5.5.5.5
# slave-announce-port 1234
# requirepass foobared
# rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52
# rename-command CONFIG ""
# maxclients 10000
maxmemory 256mb
# maxmemory-policy noeviction
# maxmemory-samples 5
lazyfree-lazy-eviction no
lazyfree-lazy-expire no
lazyfree-lazy-server-del no
slave-lazy-flush no
appendonly no
appendfilename "appendonly.aof"
# appendfsync always
appendfsync everysec
# appendfsync no
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
aof-use-rdb-preamble no
lua-time-limit 5000
# cluster-enabled yes
# cluster-config-file nodes-6379.conf
# cluster-node-timeout 15000
# cluster-slave-validity-factor 10
# cluster-migration-barrier 1
# cluster-require-full-coverage yes
# cluster-slave-no-failover no
# cluster-announce-ip 10.1.1.5
# cluster-announce-port 6379
# cluster-announce-bus-port 6380
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
# notify-keyspace-events Elg
# notify-keyspace-events Ex
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-size -2
list-compress-depth 0
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
stream-node-max-bytes 4096
stream-node-max-entries 10
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
# client-query-buffer-limit 1gb
# proto-max-bulk-len 512mb
hz 10
aof-rewrite-incremental-fsync yes
rdb-save-incremental-fsync yes
# lfu-log-factor 10
# lfu-decay-time 1
# activedefrag yes
# active-defrag-ignore-bytes 100mb
# active-defrag-threshold-lower 10
# active-defrag-threshold-upper 100
# active-defrag-cycle-min 25
# active-defrag-cycle-max 75 Reiniciamos Redis y PHP para cargar su configuración.
systemctl restart redis-server.service
systemctl status redis-server.service
systemctl restart php8.0-fpm.service
systemctl status php8.0-fpm.serviceCreación de un sitio web
Para estos ejemplos usaremos la carpeta raíz «/webs/» y el dominio «example.com«.
Creamos la carpeta donde alojamermos nuestros sitios web.
mkdir /webs/
cd /webs/Y aquí crearemos tantos sitios como queramos. En este caso nuestro sitio de ejemplo.
mkdir /webs/example.onion/Configuración del sitio en nginx
Accedemos y creamos el fichero de configuración.
cd /etc/nginx/sites-available/
vim example.onion.confCon el siguiente contenido:
server {
listen 127.0.0.1:80;
server_tokens off;
root /webs/example.onion;
index index.php index.html;
location = /favicon.ico {
log_not_found off;
access_log off;
}
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
location ~ /.well-known {
allow all;
}
location ~ /.ht {
deny all;
}
location / {
try_files $uri $uri/ /index.php;
}
location ~ .php$ {
include wordpress_fastcgi_8_0.conf;
}
}Creamos el enlace simbólico y reiniciamos nginx para activar esta configuración.
ln -s /etc/nginx/sites-available/example.onion.conf /etc/nginx/sites-enabled/
nginx -t
nginx -s reloadReiniciamos el nginx para cargar la nueva configuración.
nginx -t
nginx -s reloadConfiguración de la base de datos
Crearemos la base de datos para el sitio web que vamos a usar. Primero accedemos a la base de datos.
mysql -u root -pY crearemos la base de datos, el usuario y contraseña y activaremos los privilegios.
CREATE DATABASE example CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci;
GRANT ALL ON example.* TO 'example'@'localhost' IDENTIFIED BY 'la_contraseña_aqui';
FLUSH PRIVILEGES;
quitCreación del sitio web
Ahora ya tenemos todos los elementos necesarios para la creación de nuestro sitio.
cd /webs/example.onion/
wp core download --allow-root
wp config create --dbprefix=wpprefix_ --locale=en_US --dbname=example --dbuser=example --dbpass='la_contraseña_aqui' --dbcharset=utf8mb4 --dbcollate=utf8mb4_general_ci --allow-rootY haremos la instalación del sitio:
wp core install --url="example.onion" --title="Mi WordPress" --admin_user="AdminDeWordPress" --admin_password="PasswordDeWordPress" --admin_email="example@example.com" --allow-rootY haremos una actualizaciónd e los ficheros y sus permisos.
cd /webs/example.onion/
chown -R www-data:www-data ./
find /webs/example.onion/ -type d -exec chmod 750 {} \;
find /webs/example.onion/ -type f -exec chmod 640 {} \;Hay que tener presente que en este caso WordPress funcionará destrás de un proxy, por lo que en el fichewro de configuración deberíamos hacer algunos cambios.
define('WP_HOME', 'http://example.onion';
define('WP_SITEURL', 'http://example.onion');
define('WP_HTTP_BLOCK_EXTERNAL', true);
define('WP_ACCESSIBLE_HOSTS', '*.wordpress.org');
define('WP_PROXY_HOST', '127.0.0.1');
define('WP_PROXY_PORT', '9050');
define('WP_PROXY_TYPE', 'CURLPROXY_SOCKS5');Con esto podremos conectarnos a la red Tor y lanzar nuestro nuevo sitio web…

Asegurando el .onion
recuerda que los servidores Tor pueden llegar a desaparecer, o si has de migrar un sitio entre servidores, necesitarás almacenar las claves de la configuración.
En estos casos, recuerda copiar y guardar el contenido de la carpeta de cada uno de los sitios que tengas en el servidor.
/var/lib/tor/site_1/Sobre este documento
Este documento está regulado por la licencia EUPL v1.2, publicado en WP SysAdmin y creado por Javier Casares. Por favor, si utilizas este contenido en tu sitio web, tu presentación o cualquier material que distribuyas, recuerda hacer una mención a este sitio o a su autor, y teniendo que poner el material que crees bajo licencia EUPL.

