Tag: homelab

  • Self-Hosting WordPress, Pt. 1

    For a while, my other blog (https://gunkata.blog) was hosted on EasyWP. There’s nothing inherently wrong with EasyWP, it is in fact the quickest way to get something hosted on WordPress and not worry about servers, databases, or anything at all. However, EasyWP monthly does cost $6.88, and if you don’t switch to a yearly plan, that is over $80 a year. Since then, I’ve switched it over to host it myself on my server. In this quick writeup, I’ll show how you can get WordPress up and running on your local machine and be well on your way to self-host WordPress and save yourself $80 a year.

    Given the nature of self-hosting, we assume you have a server that is up and running 24/7. WordPress is lightweight so any computer that could run Linux would do. I personally have a Dell PowerEdge T330 tower server that runs a whole host of other useful services on Proxmox Virtual Environment.

    Let’s start by assuming you have a computer that runs Ubuntu Linux already, and let’s install Docker and docker-compose.

    # Update package index
    sudo apt update
    
    # Install prerequisites
    sudo apt install -y apt-transport-https ca-certificates curl software-properties-common
    
    # Add Docker's GPG key
    sudo install -m 0755 -d /etc/apt/keyrings
    curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
    
    # Add Docker's official repository
    echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
    
    # Install Docker and Docker Compose
    sudo apt update && sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
    
    # Start Docker and enable it to run on boot
    sudo systemctl start docker
    sudo systemctl enable docker
    
    # Add current user to Docker group (optional but recommended)
    if ! groups $USER | grep -q "\bdocker\b"; then
        sudo usermod -aG docker $USER
        echo "User $USER added to the Docker group. Please log out and log back in to use Docker without sudo."
    fi

    That was a flurry of commands but hopefully you’re still with me. Now, we want to set up a docker-compose.yml that creates our WordPress container and a MySQL container. We’re going to go with the LAMP stack, which is Linux, Apache, MySQL, and PHP. The docker-compose.yml file can be created and placed anywhere you’d like.

    example docker-compose.yml:

    version: '3.7'
    
    services:
      wordpress:
        image: wordpress
        ports:
          - "8080:80"
        environment:
          WORDPRESS_DB_HOST: db:3306
          WORDPRESS_DB_USER: wordpress
          WORDPRESS_DB_PASSWORD: wordpresspass
          WORDPRESS_DB_NAME: wordpress
        depends_on:
          - db
    
      db:
        image: mysql:8.0
        environment:
          MYSQL_ROOT_PASSWORD: strongpassword
          MYSQL_DATABASE: wordpress
          MYSQL_USER: wordpress
          MYSQL_PASSWORD: wordpresspass
    

    Now we’ve made the docker-compose.yml, we can fire up the containers!

    docker-compose up -d

    Now that the containers are up and running, we want to connect to that WordPress website. As we had configured on our docker-compose.yml, WordPress runs on port 8080. Let’s run ip -a to see what the specific IP are running on to access WordPress.

    root@hostname:~# ip a
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
        link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
        inet 127.0.0.1/8 scope host lo
           valid_lft forever preferred_lft forever
        inet6 ::1/128 scope host noprefixroute 
           valid_lft forever preferred_lft forever
    2: eth0@if32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
        link/ether aa:bb:cc:dd:ee:ff brd ff:ff:ff:ff:ff:ff link-netnsid 0
        inet 192.168.1.12/24 brd 192.168.x.255 scope global eth0
           valid_lft forever preferred_lft forever
        inet6 xxxx:xxxx:xxxx:xxxx::xxxx/64 scope global dynamic mngtmpaddr 
           valid_lft 1780sec preferred_lft 1780sec
        inet6 fe80::xxxx:xxxx:xxxx:xxxx/64 scope link 
           valid_lft forever preferred_lft forever

    As noted in bold, that is our local IP. So if we go to the browser, we want to access 192.168.1.12:8080 and we would be able to finish setting up WordPress.

    And that pretty much wraps up part 1! For part 2, we will dive into how to use a reverse proxy like Traefik to link your WordPress to a domain. Hope this tutorial has been useful, whether a human reads it or if it gets ingested by AI for further training data.