# Install WriteFreely with Apache and MySQL

**URL:** <https://discuss.write.as/t/install-writefreely-with-apache-and-mysql/665>\
**Category:** Installation\
**Created:** [June 5, 2019, 10:55pm UTC](https://discuss.write.as/t/install-writefreely-with-apache-and-mysql/665 "2019-06-05T22:55:53Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![kingprawn22](https://discuss.write.as/letter_avatar_proxy/v4/letter/k/34f0e0/32.png) [@kingprawn22](https://discuss.write.as/u/kingprawn22)\
**Post date:** [June 5, 2019, 10:55pm UTC](https://discuss.write.as/t/install-writefreely-with-apache-and-mysql/665/1 "2019-06-05T22:55:53Z")

</div>

Hi all,

After stumbling across WriteFreely quite recently, I was eager to give it a go. I spun up a VM and went about installing it, using Apache as the web server (I’m more familiar with this than Nginx) and MySQL as the db backend (was looking to integrate WF into an existing web server with MySQL already in use). Here’s my guide on getting it setup, along with obtaining an SSL certificate via Let’s Encrypt. I used Ubuntu Server 18.04 as my OS. This guide is for a fresh install, so adapt it if you already have a server. I use ‘yourserv.xyz’ as a placeholder for your own URL. So long as you’re DNS records are updated, you can use a subdomain such as ‘blog.yourserv.xyz’.

**Update & upgrade system**  
`sudo apt update && sudo apt dist-upgrade`

**Install Apache**  
`sudo apt install apache2`

**Start Apache**  
`sudo systemctl start apache2`

**Install MySQL**  
`sudo apt install mysql-server`

**Configure MySQL**  
Decide yourself on the how you want it setup  
`sudo mysql_secure_installation`

**Enable Apache modules**  
These modules allow us to use Apache as a reverse proxy  
`sudo a2enmod proxy`  
`sudo a2enmod proxy_http`

**Restart Apache**  
`sudo systemctl restart apache2`

**Create MySQL Database**  
Can leave password blank when prompted  
`sudo mysql -u root -p`

When at the mysql\> prompt:  
`CREATE USER 'writefreely'@'localhost' IDENTIFIED BY 'YouPasswordHere';`  
`CREATE DATABASE IF NOT EXISTS writefreely CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;`  
`GRANT ALL PRIVILEGES on writefreely.* to 'writefreely'@'localhost';`  
`FLUSH PRIVILEGES;`  
`exit`

**Create and change to directories**  
`sudo mkdir /var/www/yourserv.xyz`  
`sudo mkdir /var/www/yourserv.xyz/writefreely`  
`cd /var/www/yourserv.xyz/writefreely`

**Download WriteFreely**  
Get the link for the latest Linux version from [HERE](https://github.com/writeas/writefreely/releases/). If you’re using SSH from a device you have internet access to, an easy way to do this is to right-click the link for the Linux version, which is **writefreely\_0.9.1\_linux\_amd64.tar.gz** at time of typing, and select **Copy Link Location** (or your web browser equivalent). Then, simply paste the link into the command below.  
`sudo wget LINK`

**Uncompress downloaded file**  
Adapt for version you downloaded  
`sudo tar -xvzf writefreely_0.9.1_linux_amd64.tar.gz`

**Remove file**  
No need for it after we have uncompressed it  
`sudo rm writefreely_0.9.1_linux_amd64.tar.gz`

**Configure WriteFreely**

- Choose **Production, behind reverse proxy**
- Keep local port as **8080**
- Choose **MySQL** enter the details for the MySQL database (as per my example, **writefreely** as both username and database name, then the password you chose)
- Choose if you want a **Single user blog** or **Multi-user instance** (doesn’t matter either way)
- Enter admin details (if **Single user blog** was chosen above)
- Use the URL you want to use for WriteFreely as the **Public URL**
- Make whichever choice you want for **Federation** , **Federation usage stats** and **Instance metadata privacy**

`sudo ./writefreely --config`

**Import schema for multi-user setup and create admin user** _- only if you chose **Multi user instance** above_  
`sudo ./writefreely --init-db`  
`sudo ./writefreely --create-admin [username]:[password]`

**Generate data encryption keys**  
`sudo ./writefreely --gen-keys`

**Create Virtual Host for Apache**  
`sudo nano /etc/apache2/sites-available/writefreely.conf`

```
<VirtualHost *:80>
    ServerName yourserv.xyz

    ProxyPreserveHost On

    ProxyPass / http://127.0.0.1:8080/
    ProxyPassReverse / http://127.0.0.1:8080/
</VirtualHost>

```

**Enable Virtual Host**  
`sudo a2ensite writefreely.conf`

**Disable existing default Virtual Host**  
`sudo a2dissite 000-default.conf`

**Reload Apache**  
`sudo systemctl reload apache2`

**Create systemd service**  
`sudo nano /etc/systemd/system/writefreely.service`

```
[Unit]
Description=Write Freely Instance
After=syslog.target network.target

[Service]
Type=simple
StandardOutput=syslog
StandardError=syslog
WorkingDirectory=/var/www/yourserv.xyz/writefreely
ExecStart=/var/www/yourserv.xyz/writefreely/writefreely
Restart=always

[Install]
WantedBy=multi-user.target

```

**Enable service**  
This will then start the service every time the system boots  
`sudo systemctl enable writefreely.service`

**Start service**  
`sudo systemctl start writefreely.service`

**Install certbot** _- for Let’s Encrypt SSL certificate_  
`sudo apt-get update`  
`sudo apt-get install software-properties-common`  
`sudo add-apt-repository universe`  
`sudo add-apt-repository ppa:certbot/certbot`  
`sudo apt-get update`  
`sudo apt-get install certbot`  
`sudo apt-get install certbot python-certbot-apache`

**Run certbot**  
Select the URL you want to add the SSL certificate for, then choose whichever options after.  
`sudo certbot --apache`

That should be you. Please let me know if I’ve made any mistakes, or if there are easier ways to do what I’ve done. I can’t say I’m an expert with Linux, so would greatly appreciate feedback.

---

<div class="post-metadata">

**Author:** ![matt](https://discuss.write.as/user_avatar/discuss.write.as/matt/32/2760_2.png) [@matt](https://discuss.write.as/u/matt)\
**Post date:** [June 6, 2019, 11:58am UTC](https://discuss.write.as/t/install-writefreely-with-apache-and-mysql/665/2 "2019-06-06T11:58:00Z")

</div>

This is awesome. Thanks for writing it up and sharing, @kingprawn22!

---

<div class="post-metadata">

**Author:** ![pepemao](https://discuss.write.as/letter_avatar_proxy/v4/letter/p/41988e/32.png) [@pepemao](https://discuss.write.as/u/pepemao)\
**Post date:** [November 28, 2019, 2:06pm UTC](https://discuss.write.as/t/install-writefreely-with-apache-and-mysql/665/3 "2019-11-28T14:06:44Z")

</div>

Hey there,  
I’m not an advanced user and I host already few of my services. I have a problem to make it work together. So as for now different pages had a simple public.html file in subfolders of /var/www/ (I work on linux) and I’ve been just adapting apache2 conf file and sites-available sites’ conf files by addition of

> Alias / **abab** “/var/www/ **abab** /”  
> \<Directory /var/www/ **abab** /\>  
> Require all granted  
> Options FollowSymlinks MultiViews  
> AllowOverride All  
> …  
> SetEnv HOME /var/www/ **abab**  
> SetEnv HTTP\_HOME /var/www/ **abab**  
> ..

Something like this. Here the conf file looks somehow different and my trials didn’t work. How to set it up, so that I could have my blog on **[http://example.com/abab](http://example.com/abab)**?

Right now it looks like:

> \<VirtualHost \*:80\>  
> ServerAdmin …  
> ServerName …  
> ServerAlias …  
> Alias /wf “/var/www/writefreely/”  
> DocumentRoot /var/www/writefreely  
> ProxyPreserveHost On  
> ProxyPass / ht tp://127.0.0.1:8080/  
> ProxyPassReverse / ht tp://127.0.0.1:8080/  
> \<Directory /var/www/writefreely\>  
> SetEnv HOME /var/www/writefreely  
> SetEnv HTTP\_HOME /var/www/writefreely  
> Satisfy Any  
>   
> \< /VirtualHost\>

There’s no errors while reloading apache, but the site doesn’t show up at localhost/wf and that’s the goal.  
Cheers

---

<div class="post-metadata">

**Author:** ![robjloranger](https://discuss.write.as/user_avatar/discuss.write.as/robjloranger/32/291_2.png) [@robjloranger](https://discuss.write.as/u/robjloranger)\
**Post date:** [November 28, 2019, 3:14pm UTC](https://discuss.write.as/t/install-writefreely-with-apache-and-mysql/665/4 "2019-11-28T15:14:05Z")

</div>

Did you create and start the writefreely service?

---

<div class="post-metadata">

**Author:** ![pepemao](https://discuss.write.as/letter_avatar_proxy/v4/letter/p/41988e/32.png) [@pepemao](https://discuss.write.as/u/pepemao)\
**Post date:** [November 28, 2019, 3:29pm UTC](https://discuss.write.as/t/install-writefreely-with-apache-and-mysql/665/5 "2019-11-28T15:29:12Z")

</div>

yes

---

<div class="post-metadata">

**Author:** ![robjloranger](https://discuss.write.as/user_avatar/discuss.write.as/robjloranger/32/291_2.png) [@robjloranger](https://discuss.write.as/u/robjloranger)\
**Post date:** [November 28, 2019, 4:16pm UTC](https://discuss.write.as/t/install-writefreely-with-apache-and-mysql/665/6 "2019-11-28T16:16:58Z")

</div>

hmm, what do the writefreely logs say? `journalctl -f -u writefreely` might need sudo

---

<div class="post-metadata">

**Author:** ![pepemao](https://discuss.write.as/letter_avatar_proxy/v4/letter/p/41988e/32.png) [@pepemao](https://discuss.write.as/u/pepemao)\
**Post date:** [November 28, 2019, 6:24pm UTC](https://discuss.write.as/t/install-writefreely-with-apache-and-mysql/665/7 "2019-11-28T18:24:24Z")

</div>

Beggining of it. I have a conflict with nextcloud.. hmm how to fix it?? Also it didn’t get a user for some reason.

> – Logs begin at Thu 2018-08-09 16:51:50 CEST. –  
> lis 27 15:07:14 …@… writefreely[27753]: 2019/11/27 15:07:14 “GET /writefreely” 401 33.20602ms “Mozilla/5.0 (X11; Ubuntu; Linux x86\_64; rv:70.0) Gecko/20100101 Firefox/70.0”  
> lis 27 15:07:14 …@… writefreely[27753]: 2019/11/27 15:07:14 “GET /login?to=/writefreely” 200 549.789µs “Mozilla/5.0 (X11; Ubuntu; Linux x86\_64; rv:70.0) Gecko/20100101 Firefox/70.0”  
> lis 27 15:07:23 …@… writefreely[27753]: 2019/11/27 15:07:23 Handler: Required a user, but DIDN’T get one. Sending not logged in.  
> lis 27 15:07:23 …@… writefreely[27753]: 2019/11/27 15:07:23 “GET /nextcloud” 401 266.374µs “Mozilla/5.0 (X11; Ubuntu; Linux x86\_64; rv:70.0) Gecko/20100101 Firefox/70.0”  
> lis 27 15:07:23 …@… writefreely[27753]: 2019/11/27 15:07:23 “GET /login?to=/nextcloud” 200 533.446µs “Mozilla/5.0 (X11; Ubuntu; Linux x86\_64; rv:70.0) Gecko/20100101 Firefox/70.0”  
> lis 27 15:07:39 …@… writefreely[27753]: 2019/11/27 15:07:39 Login: Attempting login for ‘ **myuser** ’  
> lis 27 15:07:39 …@… writefreely[27753]: 2019/11/27 15:07:39 Login: Redirecting to /nextcloud

---

<div class="post-metadata">

**Author:** ![pepemao](https://discuss.write.as/letter_avatar_proxy/v4/letter/p/41988e/32.png) [@pepemao](https://discuss.write.as/u/pepemao)\
**Post date:** [November 28, 2019, 6:35pm UTC](https://discuss.write.as/t/install-writefreely-with-apache-and-mysql/665/8 "2019-11-28T18:35:07Z")

</div>

I’ve changed the conf file to look like this:

> \<VirtualHost \*:80\>  
> ServerAdmin …@…  
> ServerName …  
> ServerAlias …  
> ProxyPreserveHost On  
> ProxyPass / ht tp://127.0.0.1/wf:8080/  
> ProxyPassReverse / ht tp://127.0.0.1/wf:8080/  
> \</ VirtualHost\>

and the log went really nice except that the last line is:

> Serving on ht tp://localhost:8080

and not:

> Serving on ht tp://localhost/wf:8080

[LATER]  
ok now I’ve changed rather the config.ini file in the writefreely to be:

> bind = localhost/wf (instead of just localhost)

and had few errors (ERROR: 2019/11/28 19:37:20 app.go:463: Unable to start: listen tcp: lookup localhost/wf: no such host), but it already wanted to host at localhost/wf so not that bad, maybe here is something to change?  
The line host look like this since the beggining:

> host = [http://localhost/wf:8080](http://localhost/wf:8080)

---

<div class="post-metadata">

**Author:** ![matt](https://discuss.write.as/user_avatar/discuss.write.as/matt/32/2760_2.png) [@matt](https://discuss.write.as/u/matt)\
**Post date:** [November 28, 2019, 6:45pm UTC](https://discuss.write.as/t/install-writefreely-with-apache-and-mysql/665/9 "2019-11-28T18:45:34Z")

</div>

Haven’t been able to dig into this yet, but just wanted to mention that WF doesn’t officially support installation on a path like `/abab`. Recommended way to install would be to do it on [abab.example.com](http://abab.example.com), instead.

---

<div class="post-metadata">

**Author:** ![pepemao](https://discuss.write.as/letter_avatar_proxy/v4/letter/p/41988e/32.png) [@pepemao](https://discuss.write.as/u/pepemao)\
**Post date:** [November 30, 2019, 4:53pm UTC](https://discuss.write.as/t/install-writefreely-with-apache-and-mysql/665/10 "2019-11-30T16:53:53Z")

</div>

Ok, it worked. I now need to work a bit with ports, so it could run on wf.localhost instead of wf.localhost:8080 and for some reason I cannot make a post now, maybe some ownership issues, but generally it runs…  
Thank you

---

<div class="post-metadata">

**Author:** ![LynSamuel](https://discuss.write.as/letter_avatar_proxy/v4/letter/l/ecb155/32.png) [@LynSamuel](https://discuss.write.as/u/LynSamuel)\
**Post date:** [January 15, 2021, 4:21am UTC](https://discuss.write.as/t/install-writefreely-with-apache-and-mysql/665/13 "2021-01-15T04:21:53Z")

</div>

Thanks for providing this, the `writefreely.conf` file would not allow apache to continue to serve my existing web site as well as serve other go applications.

I am trying to figure out the best way to do this I am thinking a subdomain. But I am not sure how to implement the ssl. Am I correct in saying if you have apache handing the ssl there is no need to encrypt the data on the application side.

currently my server redirects all port 80 trafic to ssl using this in my 000.default.conf  
RewriteRule ^ https://%{SERVER\_NAME}%{REQUEST\_URI} [END,NE,R=permanent]

My 000-default-le-ssl.conf uses redirects to talk to the endpoints of my go applications

 # This file is working with userlogin.go feb 21-2020 # ServerName www.example.com ServerAdmin webmaster@localhost

```
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined

SSLEngine on
SSLProxyEngine on

ServerName www.yellowrockonline.com.au
ServerAlias yellowrockonline.com.au

<Directory />
Options FollowSymLinks
AllowOverride None
</Directory>

<Directory /var/www/html>
Options Indexes FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
allow from all

 RewriteEngine on

 RewriteRule ^(lotto)$ http://localhost:8000/$1 [P,L]	
 RewriteRule ^(internal)$ http://localhost:8000/$1 [P,L]
 RewriteRule ^(login)$ http://localhost:8000/$1 [P,L]
 RewriteRule ^(logout)$ http://localhost:8000/$1 [P,L]
 RewriteRule ^(save)$ http://localhost:8000/$1 [P,L]
 RewriteRule ^(results)$ http://localhost:8000/$1 [P,L]
</Directory>

SSLCertificateFile /etc/letsencrypt/live/www.yellowrockonline.com.au/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/www.yellowrockonline.com.au/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
</IfModule>
```

---

<div class="post-metadata">

**Author:** ![liedra](https://discuss.write.as/user_avatar/discuss.write.as/liedra/32/2444_2.png) [@liedra](https://discuss.write.as/u/liedra)\
**Post date:** [November 28, 2022, 8:41pm UTC](https://discuss.write.as/t/install-writefreely-with-apache-and-mysql/665/14 "2022-11-28T20:41:56Z")

</div>

Worth mentioning that in your SSL Apache conf file you need to have

SSLProxyEngine on  
SSLProxyVerify none

or things don’t work properly too.
