Ga naar inhoud

Exonet Hosting Guide

Table of Contents


Overview

Exonet is Lemone's primary hosting provider for WordPress projects. This guide covers common operations for managing websites on Exonet infrastructure.

Exonet Server: web01.exonet.lemone.network


Creating a New Website

Prerequisites

  • Access to Exonet server via SSH
  • Trellis project configured locally
  • Ansible installed

Setup Process

Step 1: Configure Trellis

Ensure your Trellis configuration is complete:

# trellis/group_vars/production/wordpress_sites.yml
wordpress_sites:
  example.com:
    site_hosts:
      - canonical: example.com
        redirects:
          - www.example.com
    local_path: ../site
    repo: git@codepot.nl:your-project/repository.git
    repo_subtree_path: site
    branch: main
    multisite:
      enabled: false
    ssl:
      enabled: true
      provider: letsencrypt
    cache:
      enabled: true

Step 2: Add Server to Hosts

Add the server to your production hosts file:

# trellis/hosts/production
[production]
web01.exonet.lemone.network

[web]
web01.exonet.lemone.network

Step 3: Provision the Server

Run Ansible provisioning to set up the website:

cd trellis
ansible-playbook server.yml -e env=production

This will: - Create the website directory structure - Set up Nginx configuration - Configure PHP-FPM pool - Set up Let's Encrypt SSL - Configure database

Step 4: Deploy the Site

cd trellis
./bin/deploy.sh production example.com

Step 5: Verify

  1. Check that the site is accessible at the domain
  2. Verify SSL certificate is active
  3. Test WordPress admin access
  4. Check that cache is working (if enabled)

SSL Certificates

Requesting SSL Certificates

Exonet uses Let's Encrypt for SSL certificates, managed automatically by Trellis.

Automatic SSL Setup

When you provision a new site with ssl.enabled: true, Trellis automatically: 1. Installs Certbot 2. Requests SSL certificate from Let's Encrypt 3. Configures Nginx to use HTTPS 4. Sets up automatic renewal via cron

Manual SSL Certificate Request

If you need to manually request a certificate:

# SSH into the server
ssh web01.exonet.lemone.network

# Request certificate
sudo certbot certonly --webroot -w /srv/www/example.com/current/web -d example.com -d www.example.com

SSL Certificate Renewal

Certificates auto-renew via cron. To manually renew:

sudo certbot renew

Troubleshooting SSL

Certificate not issued: - Verify DNS points to Exonet server - Check that port 80 is accessible (Let's Encrypt needs HTTP for verification) - Ensure no nginx errors: sudo nginx -t

Mixed content warnings: - Update site URL in WordPress settings to use HTTPS - Search/replace HTTP URLs in database - Check that WP_HOME and WP_SITEURL use HTTPS in .env


Deployment

Standard Deployment via GitLab CI/CD

Deployments to Exonet are automated through GitLab CI/CD pipelines.

Process: 1. Push code to main branch in GitLab 2. CI/CD pipeline runs automatically 3. Tests execute 4. If successful, deployment to production is triggered 5. Ansible deploys latest code to Exonet

Manual Deployment

If you need to deploy manually:

cd trellis
./bin/deploy.sh production example.com

What deployment does: 1. Clones latest code from repository 2. Runs Composer install 3. Compiles assets (if configured) 4. Symlinks new release 5. Runs database migrations 6. Clears cache 7. Switches to new release

Deployment Configuration

In .gitlab-ci.yml:

deploy:production:
  stage: deploy
  script:
    - cd trellis
    - ansible-playbook deploy.yml -e env=production -e site=$SITE_NAME
  only:
    - main
  when: manual

Deployment Hooks

You can add deployment hooks in Trellis:

# trellis/group_vars/production/wordpress_sites.yml
deploy_before:
  - "{{ playbook_dir }}/deploy-hooks/build-assets.sh"

deploy_after:
  - "{{ playbook_dir }}/deploy-hooks/clear-cache.sh"

Manual Rollback

If a deployment causes issues, you can manually roll back to a previous release.

Via Ansible

The safest way is to use Trellis rollback:

cd trellis
ansible-playbook rollback.yml -e env=production -e site=example.com

This automatically switches to the previous release.

Manual Rollback on Server

If Ansible isn't available, SSH into the server:

Step 1: SSH into Exonet

ssh web01.exonet.lemone.network

Step 2: Navigate to Site Directory

cd /srv/www/example.com

Directory structure:

/srv/www/example.com/
├── current -> releases/20240101120000
├── releases/
│   ├── 20240101120000  (current)
│   ├── 20231215100000  (previous)
│   └── 20231201090000  (older)
└── shared/

Step 3: Identify Previous Release

ls -la releases/

Step 4: Update Symlink

# Remove current symlink
sudo rm current

# Create new symlink to previous release
sudo ln -s releases/20231215100000 current

Step 5: Restart PHP-FPM

sudo systemctl restart php8.2-fpm

Step 6: Clear Cache

cd current
sudo -u web wp cache flush --path=web/wp

Step 7: Verify

Check that the site is working properly: - Test homepage - Check WordPress admin - Verify critical functionality

Rollback via GitLab

You can also trigger a rollback through GitLab:

  1. Go to CI/CD > Pipelines
  2. Find successful previous pipeline
  3. Click "Retry" on the deploy job
  4. This redeploys the previous version

Database Troubleshooting

Common MySQL/MariaDB Issues on Exonet

Connection Refused

Symptoms:

ERROR 2002 (HY000): Can't connect to MySQL server

Solution:

# Check if MySQL is running
sudo systemctl status mariadb

# Restart MySQL
sudo systemctl restart mariadb

# Check error logs
sudo tail -f /var/log/mysql/error.log

Too Many Connections

Symptoms:

ERROR 1040 (HY000): Too many connections

Solution:

# Check current connections
mysql -u root -p -e "SHOW PROCESSLIST;"

# Increase max_connections temporarily
mysql -u root -p -e "SET GLOBAL max_connections = 200;"

Permanent fix in /etc/mysql/mariadb.conf.d/50-server.cnf:

[mysqld]
max_connections = 200

Database Performance Issues

Check slow queries:

mysql -u root -p -e "SHOW FULL PROCESSLIST;"

Enable slow query log:

SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 2;

Optimize tables:

mysqlcheck -u root -p --optimize --all-databases

Repairing Corrupted Tables

# Check for corrupted tables
mysqlcheck -u root -p --check --all-databases

# Repair corrupted tables
mysqlcheck -u root -p --repair --all-databases

Import/Export Database

Export database:

mysqldump -u dbuser -p dbname > backup.sql

Import database:

mysql -u dbuser -p dbname < backup.sql

Large import (bypass max_packet issues):

mysql -u dbuser -p --max_allowed_packet=512M dbname < backup.sql

Access Denied Issues

Reset database user password:

mysql -u root -p

USE mysql;
ALTER USER 'dbuser'@'localhost' IDENTIFIED BY 'new_password';
FLUSH PRIVILEGES;

Disk Space Issues

Check database sizes:

SELECT
    table_schema AS 'Database',
    ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS 'Size (MB)'
FROM information_schema.tables
GROUP BY table_schema;

Clean up binary logs:

# Check binary log size
sudo du -sh /var/lib/mysql/mysql-bin.*

# Purge old binary logs (keep last 3 days)
mysql -u root -p -e "PURGE BINARY LOGS BEFORE DATE_SUB(NOW(), INTERVAL 3 DAY);"


See Also