This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| computing:selfhostedwp [2019/08/18 01:04] – oemb1905 | computing:selfhostedwp [2026/04/12 15:53] (current) – oemb1905 | ||
|---|---|---|---|
| Line 11: | Line 11: | ||
| ------------------------------------------- | ------------------------------------------- | ||
| - | This tutorial is for setting up a self-hosted WordPress instance on Debian GNU/ | + | This tutorial is for setting up a self-hosted WordPress instance on Debian GNU/Linux. This tutorial assumes you have some familiarity setting up a LAMP stack. If you need help with that, check out [[https:// |
| - | sudo apt install | + | sudo apt install |
| | | ||
| - | Move index.php to the top priority | + | Sometimes dpkg can choose which version of php you want and it's not always |
| | | ||
| - | sudo nano / | + | sudo apt-get install php8.4-{common,cgi, |
| - | < | + | |
| | | ||
| - | Above, we installed phpmyadmin, which you should | + | Apache2 will set up a 000-default.conf automatically and your host should |
| - | sudo htpasswd | + | sudo apt install certbot letsencrypt python3-certbot-apache |
| - | | + | sudo certbot --authenticator standalone --installer apache -d site1.com --pre-hook " |
| + | crontab -e | ||
| + | | ||
| | | ||
| - | Enter the following in the file that opens: | + | Once you have the LAMP stack setup and TLS properly configured, it's time to make some decisions on your php handler and your apache2 multi-processing module (mpm). There' |
| | | ||
| - | AuthType Basic | + | |
| - | AuthName " | + | sudo apt install php8.4-fpm php8.4-cgi |
| - | AuthUserFile / | + | sudo a2enmod ssl |
| - | Require valid-user | + | sudo a2enmod headers |
| + | sudo a2enmod cache | ||
| + | sudo a2enmod rewrite | ||
| + | sudo a2enmod setenvif | ||
| + | sudo a2dismod php8.1 | ||
| + | sudo a2dismod php8.2 | ||
| + | sudo a2dismod php8.3 | ||
| + | sudo a2dismod mpm_prefork | ||
| + | sudo a2enmod mpm_event | ||
| + | sudo a2enmod proxy | ||
| + | sudo a2enmod proxy_fcgi | ||
| + | sudo a2enconf php8.4-fpm | ||
| + | sudo a2enconf php8.4-cgi | ||
| + | sudo apache2ctl configtest | ||
| + | sudo systemctl restart apache2 | ||
| + | sudo systemctl restart php8.4-fpm | ||
| + | |||
| + | There are two standard ways to configure php-fpm. One of those is to use ProxyPassReverse, | ||
| + | |||
| + | < | ||
| + | SetHandler " | ||
| + | </ | ||
| + | |||
| + | That takes care of configuring php-fpm and mpm_event. Before proceeding, navigate to your tld.domain in a web browser and make sure that your site resolves properly. If it does not, then you should debug your setup. To do that, there' | ||
| + | |||
| + | sudo apachectl -M | grep ' | ||
| + | sudo apachectl -M | grep ' | ||
| + | sudo apache2ctl configtest | ||
| + | |||
| + | The output of mpm should show mpm_event and the output of proxy grep should show proxy_module and proxy_fcgi_module in use. If not, trace back over the steps above and see what went wrong. As for configtest, it should either tell you what's wrong or return " | ||
| + | |||
| + | sudo apt install phpmyadmin | ||
| + | sudo htpasswd -c / | ||
| + | sudo nano / | ||
| + | <AuthType Basic> | ||
| + | | ||
| + | | ||
| + | | ||
| + | |||
| + | If you don't need something as heavy as phpmyadmin, you can optionally create a phpinfo page instead: | ||
| + | |||
| + | sudo nano / | ||
| + | sudo htpasswd -c / | ||
| + | sudo nano / | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | <Require valid-user> | ||
| + | |||
| + | Use these tools to make sure your handler and multi-processing module are configured to your preference and functional. After that's all working, let's make sure that your WordPress index.php is set to top priority as follows: | ||
| | | ||
| - | Close and save the file. Let's set up a database now for the WordPress instance: | + | sudo nano / |
| + | < | ||
| + | |||
| + | Close and save the file. Let' | ||
| sudo mysql -u root -p | sudo mysql -u root -p | ||
| - | | + | CREATE DATABASE databasename DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci; |
| - | | + | GRANT ALL ON databasename.* TO ' |
| - | | + | FLUSH PRIVILEGES; |
| - | | + | EXIT; |
| - | Next up, it is time to allow overrides in your primary apache configuration: | + | Next up, it is time to allow overrides in your primary apache configuration. This is optional but/and it allows WordPress extensions to make configuration changes to .htaccess and/or other changes to the web server. It's often helpful, but you can leave it off if you prefer and configure everything manually. |
| sudo nano / | sudo nano / | ||
| - | <Directory / | + | < |
| - | ... | + | |
| - | | + | |
| - | ... | + | |
| | | ||
| - | Okay, let's now enable fast cgi and rewrite php modules and then check your config. | + | Let's now shell into our instance |
| - | + | ||
| - | sudo a2enmod rewrite | + | |
| - | sudo a2enmod proxy_fcgi | + | |
| - | sudo apache2ctl configtest | + | |
| - | + | ||
| - | If you have not set the fully qualified domain name, you may get an error - that can safely be ignored unless you desire it. If you want to get rid of that, navigate to ''/ | + | |
| - | | + | |
| - | mkdir wpdownload | + | |
| - | cd wpdownload | + | |
| curl -O https:// | curl -O https:// | ||
| tar xzvf latest.tar.gz | tar xzvf latest.tar.gz | ||
| - | | + | |
| - | sudo chmod 660 ~/Downloads/ | + | |
| - | cp ~/Downloads/ | + | |
| - | | + | |
| Okay, we will need the files and directories I created once we get it running. | Okay, we will need the files and directories I created once we get it running. | ||
| - | sudo cp -ar ~/ | + | sudo mv ~/ |
| - | sudo cp -ar ~/ | + | |
| - | Now, let's set up permissions and ownership: | + | Now, create proper |
| sudo chown -R www-data: | sudo chown -R www-data: | ||
| Line 79: | Line 117: | ||
| sudo chmod -R 755 / | sudo chmod -R 755 / | ||
| - | Ok, time to grab ' | + | It's now time to configure your '' |
| | | ||
| curl -s https:// | curl -s https:// | ||
| sudo nano / | sudo nano / | ||
| - | <swap these into the proper section in the wp-config.php file> | + | <Replace |
| - | + | ||
| - | Enter user name and password for database in '' | + | |
| - | + | ||
| - | sudo nano / | + | |
| - | + | ||
| - | It looks something like this: | + | |
| | | ||
| - | /** The name of the database | + | Sometimes, |
| - | define(' | + | |
| - | + | ||
| - | /** MySQL database username */ | + | |
| - | define(' | + | |
| - | + | ||
| - | /** MySQL database password */ | + | |
| - | define(' | + | |
| - | + | ||
| - | Let' | + | |
| sudo nano / | sudo nano / | ||
| < | < | ||
| - | | ||
| - | Plug-ins and other WP services can mess with the '' | ||
| - | sudo nano /var/www/site1.com/public_html/ | + | Let's now visit site1.com |
| - | + | ||
| - | | + | |
| - | < | + | |
| - | RewriteEngine On | + | |
| - | RewriteBase / | + | a2enmod cache |
| - | RewriteRule ^index\.php$ - [L] | + | a2enmod expires |
| - | RewriteCond %{REQUEST_FILENAME} !-f | + | a2enmod headers |
| - | RewriteCond %{REQUEST_FILENAME} !-d | + | a2enmod rewrite |
| - | RewriteRule . /index.php [L] | + | |
| - | </ | + | After isntalling memcached and enabling those modules, navigate to your web root and adjust your .htaccess as follows: |
| - | # END WordPress | + | |
| + | < | ||
| + | < | ||
| + | ExpiresActive On | ||
| + | ExpiresByType image/jpg " | ||
| + | ExpiresByType image/jpeg " | ||
| + | ExpiresByType image/gif " | ||
| + | ExpiresByType image/png " | ||
| + | ExpiresByType text/css " | ||
| + | ExpiresByType text/html " | ||
| + | ExpiresByType text/ | ||
| + | ExpiresDefault " | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | < | ||
| + | < | ||
| + | RewriteEngine On | ||
| + | | ||
| + | | ||
| + | RewriteRule ^index\.php$ - [L] | ||
| + | RewriteCond %{REQUEST_FILENAME} !-f | ||
| + | RewriteCond %{REQUEST_FILENAME} !-d | ||
| + | RewriteRule . /index.php [L] | ||
| + | < | ||
| + | Header set Timing-Allow-Origin " | ||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | < | ||
| + | < | ||
| + | | ||
| + | Header always set X-Content-Type-Options " | ||
| + | Header always set X-Frame-Options " | ||
| + | Header always set Referrer-Policy " | ||
| + | # HSTS | ||
| + | Header always set Strict-Transport-Security " | ||
| + | # Feature Policy | ||
| + | Header always set Permissions-Policy " | ||
| + | # Cross Origin Openerand Embedder policies permissive for Gutenberg/ | ||
| + | Header always set Cross-Origin-Opener-Policy " | ||
| + | Header always set Cross-Origin-Embedder-Policy " | ||
| + | # Cache and download protections; | ||
| + | < | ||
| + | Header set X-Download-Options " | ||
| + | Header set X-Permitted-Cross-Domain-Policies " | ||
| + | Header set Pragma " | ||
| + | Header set Cache-Control " | ||
| + | </ | ||
| + | # Safe CSP for WordPress | ||
| + | < | ||
| + | Header set Content-Security-Policy " | ||
| + | script-src ' | ||
| + | style-src ' | ||
| + | img-src ' | ||
| + | font-src ' | ||
| + | connect-src ' | ||
| + | frame-src ' | ||
| + | media-src ' | ||
| + | object-src ' | ||
| + | base-uri ' | ||
| + | form-action ' | ||
| + | upgrade-insecure-requests;" | ||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | I was getting a stubborn TLS redirect error for images. To address this, I went into ''/ | ||
| - | Visit wordpress site and configure by opening a web browser of your choice and entering site1.com. | + | /** added this to secure images **/ |
| + | <meta http-equiv=" | ||
| - | -- !old school, but good to know how to do! -- | ||
| - | You can optionally require an sftp server instead of using the default installer with the '' | + | Personally, I don't think anyone should be using ftp. Sftp is fine, and if someone needs that, here's an example |
| sudo apt install proftpd ftp ftp-ssl | sudo apt install proftpd ftp ftp-ssl | ||
| - | | + | sudo a2enmod tls |
| cd / | cd / | ||
| sudo openssl req -new -x509 -days 7305 -nodes -out ftpd-rsa.pem -keyout ftpd-rsa-key.pem | sudo openssl req -new -x509 -days 7305 -nodes -out ftpd-rsa.pem -keyout ftpd-rsa-key.pem | ||
| sudo nano / | sudo nano / | ||
| + | <enter parameters> | ||
| | | ||
| + | Next, enter the TLS module in tls.conf underneath ''# | ||
| + | |||
| + | sudo nano / | ||
| < | < | ||
| | | ||
| Line 144: | Line 237: | ||
| | | ||
| </ | </ | ||
| + | sudo systemctl restart proftpd.service | ||
| | | ||
| - | Put this snippet under ''# | + | Refresh WordPress |
| - | + | ||
| - | sudo systemctl restart proftpd.service | + | |
| - | + | ||
| - | + | ||
| - | This tutorial | + | |
| - | --- //[[oemb1905@jonathanhaack.com|oemb1905]] | + | --- //[[alerts@haacksnetworking.org|oemb1905]] |