<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Jonathan Zweig]]></title><description><![CDATA[Tech thoughts, interesting musings.]]></description><link>https://jzweig.com/blog/</link><generator>Ghost 0.11</generator><lastBuildDate>Tue, 03 Aug 2021 00:35:51 GMT</lastBuildDate><atom:link href="https://jzweig.com/blog/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Setup Your Own Email Server with Docker]]></title><description><![CDATA[For this guide we're going to use docker compose to setup an email server with  and a web client with SSL.]]></description><link>https://jzweig.com/blog/setup-your-own-email-server-with-docker/</link><guid isPermaLink="false">5adf16cc-a85b-4c25-ab4b-f36749fd08c3</guid><category><![CDATA[docker]]></category><category><![CDATA[email]]></category><category><![CDATA[rainloop]]></category><category><![CDATA[ssl]]></category><category><![CDATA[tutorial]]></category><category><![CDATA[code]]></category><dc:creator><![CDATA[Jonathan Zweig]]></dc:creator><pubDate>Sat, 18 Mar 2017 13:35:00 GMT</pubDate><content:encoded><![CDATA[<h2 id="introduction">Introduction</h2>

<p>For this guide we're going to use docker compose.  Docker compose will allow us to neatly configure all parameters, including setting up separate docker volumes for storing data.</p>

<h2 id="step0setupdomainrecordscreatesslcerts">Step 0: Setup Domain Records &amp; Create SSL Certs</h2>

<p>See your web hosting service for how to set up A &amp; MX records.  For example, DigitalOcean users can follow <a href="https://www.digitalocean.com/community/tutorials/how-to-set-up-a-host-name-with-digitalocean">Digital Ocean's tutorial</a>.</p>

<p>See the <a href="https://github.com/tomav/docker-mailserver/wiki/Configure-SSL">SSL Configuration guide</a> to setup SSL if you don't have certificates already.</p>

<h2 id="step1downloaddockerimages">Step 1: Download docker images</h2>

<p>We'll be basing our mail server off of <a href="https://github.com/tomav/docker-mailserver">docker-mailserver</a>.  We'll also be setting up a web client using <a href="https://github.com/peperunas/docker-rainloop">rainloop</a>.  First step is to download the docker images:</p>

<pre><code>docker pull tvial/docker-mailserver:latest  
docker pull krishath/rainloop-ssl:latest  
</code></pre>

<h2 id="step2createdockercomposefile">Step 2: Create docker-compose file</h2>

<p>Create a file named <code>docker-compose.yml</code> in the root directory of your email project. <br>
In this file, we'll start with the following configuration:</p>

<pre><code>version: '2'  
services:  
</code></pre>

<h2 id="step3adddatavolumes">Step 3:  Add data volumes</h2>

<p>We'll want to store our data in docker data volumes, which will keep them isolated from containers, yet still easily sharable.  </p>

<pre><code>volumes:  
  maildata:
    driver: local
  mailstate:
    driver: local
</code></pre>

<h2 id="step4adddockermailserverconfiguration">Step 4: Add docker-mailserver configuration</h2>

<p>We'll be calling our docker-mailserver container <code>mail</code>.  </p>

<pre><code>  mail:
    image: tvial/docker-mailserver:latest
    hostname: {your_hostname}
    domainname: {your_domain}
    container_name: mail
    ports:
    - "25:25"
    - "143:143"
    - "587:587"
    - "993:993"
    volumes:
    - maildata:/var/mail
    - mailstate:/var/mail-state
    - mailconfig:/tmp/docker-mailserver/
    - {path_to_ssl}:/etc/letsencrypt/
    - /etc/localtime:/etc/localtime:ro
</code></pre>

<p>You'll need to fill in <code>{your_hostname}</code>, <code>{your_domain}</code>, <code>{your_FQDN}</code>, and <code>{path_to_ssl}</code> with your own configuration.</p>

<p>For example, if your domain MX record was pointed to <code>mail.example.com</code>:</p>

<ul>
<li><code>{your_hostname}</code> would be <code>mail</code>,</li>
<li><code>{your_domain}</code> would be <code>example.com</code></li>
<li><code>{your_FQDN}</code> would be <code>mail.example.com</code>.</li>
</ul>

<h2 id="step5addrainloopconfiguration">Step 5: Add rainloop configuration</h2>

<p>We'll be calling our rainloop container <code>webmail</code>.  Under <code>services:</code>, add the following configuration.  </p>

<pre><code>  webmail:
    image: krishath/rainloop-ssl
    container_name: webmail
    volumes:
    - {path_to_ssl}/etc/live/{your_FQDN}/fullchain.pem:/etc/ssl/cert.pem
    - {path_to_ssl}/etc/live/{your_FQDN}/privkey.pem:/etc/ssl/cert.key
    - {path_to_ssl}/dhparam.pem:/etc/ssl/certs/dhparam.pem
    - webmaildata:/webapps/rainloop/data
    - /etc/localtime:/etc/localtime:ro
    ports:
    - "443:443"
</code></pre>

<h2 id="step4bringupthecontainers">Step 4: Bring up the containers</h2>

<p>Now that everything should be configured correctly, bring up the docker containers with:  </p>

<pre><code>sudo docker-compose up -d  
</code></pre>

<p>The <code>-d</code> option starts the containers in the background. <br>
You can stop the containers at any time with <code>sudo docker-compose down</code>.  </p>

<h2 id="step5verifyeverythingisworking">Step 5: Verify everything is working</h2>

<p>Now confirm that the containers are running pointed to the correct directories with:  </p>

<pre><code>docker inspect mail  
</code></pre>

<p>This will inspect the <em>mail</em> container we brought up with <code>docker-compose</code>.  You should see the volumes you created references under <em>"Mounts"</em>. <br>
Also confirm that we can connect to the mail server using ssl:  </p>

<pre><code>openssl s_client -showcerts -connect {your_hostname}:993  
</code></pre>

<h2 id="step6createanemailaccount">Step 6: Create an email account</h2>

<p>Use the setup script to add an email account to your new mail server:  </p>

<pre><code>./setup.sh  -c mail email add email@example.com
</code></pre>

<h2 id="step7connecttoyourmailserverusingrainloop">Step 7: Connect to your mail server using rainloop</h2>

<p><img src="https://jzweig.com/blog/content/images/2017/03/rainloop-admin-login.png" alt="rainloop login">
Try to connect to your webserver's admin page. i.e.  <code>https://webmail.example.com/?admin</code> After you login use the default username and password (<code>admin</code>, <code>12345</code>), immediately change the admin password to something more secure (under "Security").</p>

<p>Now, Setup the connection to your mail server by adding a new domain (under "Domains"). <br>
<img src="https://jzweig.com/blog/content/images/2017/03/rainloop-domain-configuration.png" alt="rainloop domain configuration"></p>

<p>Test the configuration - at this point, you should be able to go to login to your email using <code>`https://webmail.example.com/</code>.</p>]]></content:encoded></item><item><title><![CDATA[Setup MediaWiki and Postgres with Docker]]></title><description><![CDATA[Use Docker to make MediaWiki setup even easier. By having MediaWiki and Postgres in docker containers, you can switch servers without reconfiguring.
]]></description><link>https://jzweig.com/blog/setup-mediawiki-and-postgres-with-docker/</link><guid isPermaLink="false">9e78bb99-3e09-4fed-85d1-0e7fca4809b4</guid><category><![CDATA[docker]]></category><category><![CDATA[postgres]]></category><category><![CDATA[mediawiki]]></category><category><![CDATA[tutorial]]></category><category><![CDATA[code]]></category><dc:creator><![CDATA[Jonathan Zweig]]></dc:creator><pubDate>Sun, 12 Mar 2017 20:38:00 GMT</pubDate><content:encoded><![CDATA[<h2 id="introduction">Introduction</h2>

<p>MediaWiki may not be the most difficult to setup, but docker can make that process even easier.  By having MediaWiki and Postgres setup in docker containers, you can also switch servers without worrying about reinstalling.</p>

<h2 id="step0setupdocker">Step 0: Setup docker</h2>

<p>I suggest following Digital Ocean's <a href="https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-ubuntu-16-04">How to Install and User Docker</a> guide.  </p>

<h2 id="step1downloaddockerimages">Step 1: Download docker images</h2>

<p>For this, I am using the official postgres image, but because <code>wikimedia/mediawiki</code> had not be updated, I decided to use <code>simplyintricate/mediawiki</code>.</p>

<pre><code>docker pull postgres  
docker pull simplyintricate/mediawiki  
</code></pre>

<h2 id="step2createwikidirectories">Step 2: Create wiki directories</h2>

<p>We need to create directories for the database data, images, and mediawiki extensions.  </p>

<pre><code>mkdir -p &lt;wiki_root&gt;/{db/data,extensions,images}  
</code></pre>

<h2 id="step3setuppostgresdockercontainer">Step 3: Setup Postgres docker container</h2>

<p>We're going to use a host volume (directory on the machine running docker) to store the database data outside of the docker postgres container.  This way, if we need to, we can restart the postgres container without losing any of our data.  </p>

<pre><code>docker run --name mediawiki-db -v &lt;wiki_root&gt;/db/data:/var/lib/postgresql/data -d postgres  
</code></pre>

<p>Now you need to setup the postgres user and database for mediawiki. <br>
Execute <code>psql -h localhost -U postgres</code> to connect to postgres and create your wiki account and database with:  </p>

<pre><code class="language-sql">CREATE USER &lt;user&gt; PASSWORD '&lt;password&gt;';  
CREATE DATABASE &lt;db&gt;;  
GRANT ALL PRIVILEGES ON DATABASE &lt;db&gt; TO &lt;user&gt;;  
</code></pre>

<h2 id="step4setupmediawikidockercontainer">Step 4: Setup MediaWiki docker container</h2>

<p>For this, we're going to link a mediawiki container to our newly created postgres container.</p>

<h6 id="step4acreatelocalsettingsphp">Step 4a: Create LocalSettings.php</h6>

<p>If you don't already have a LocalSettings.php created from a previous install, create a new one by running the mediawiki container:  </p>

<pre><code>docker run --name &lt;your_wiki_name&gt;  --link mediawiki-db:db  -p 8080:80 -d simplyintricate/mediawiki  
</code></pre>

<p>Take note: simplyintricate/mediawiki has you link your database to <code>:db</code> not <code>:postgres</code> like wikimedia/mediawiki.</p>

<p>Now log onto your wiki instance <code>&lt;server_ip&gt;:8080</code> with a browser, and initiate the setup.</p>

<p>Make sure to select 'PostgreSQL' as your Database type.</p>

<p>To find what IP the link thinks your db is on, run:  </p>

<pre><code>docker exec &lt;your_wiki_name&gt; printenv | grep 'MYSQL\|DB\|POSTGRES'  
</code></pre>

<p>Look for <code>DB_PORT_5432_TCP_ADDR</code> - You'll want to use this for the 'Database host'.</p>

<p>Once you've completed setup, keep track of where the generated LocalSettings.php file is downloaded, you'll need that in a moment.</p>

<p>After finishing setup, stop and remove your container (don't worry, the configuration you setup is stored in <code>LocalSettings.php</code>, and the database configuration is saved in your database volume).  </p>

<pre><code>docker rm -f &lt;your_wiki_name&gt;  
</code></pre>

<h6 id="step4brunmediawikicontainer">Step 4b: Run MediaWiki container</h6>

<p>First, <code>scp</code> your generated LocalSettings.php to your server, preferably to your the wiki root directory.</p>

<p>Now is the moment our hard work finally pays off. Recreate your wiki container, this time with all the data volumes mounted:</p>

<pre><code>docker run --name &lt;your_wiki_name&gt;  --link mediawiki-db:postgres  -p 8080:80 \  
-v &lt;wiki_root&gt;/data/rw:/data/rw \
-v &lt;wiki_root&gt;/images:/usr/share/nginx/html/images \
-v &lt;wiki_root&gt;/extensions:/tmp/extensions \
-v &lt;wiki_root&gt;/LocalSettings.php:/usr/share/nginx/html/LocalSettings.php \
-d simplyintricate/mediawiki
</code></pre>

<p>If you cannot connect to your wiki, try running <code>docker logs &lt;your_wiki_name&gt;</code> to debug.</p>

<h2 id="conclusion">Conclusion</h2>

<p>Now you should have a working wiki of your own!</p>]]></content:encoded></item><item><title><![CDATA[jzweig.com]]></title><description><![CDATA[<p>Work on my own site has commenced!</p>

<p>Expect to see the site in flux as I gradually add more content.</p>]]></description><link>https://jzweig.com/blog/untitled/</link><guid isPermaLink="false">6dbe0096-a13a-4c32-81e7-61b9dd68d026</guid><dc:creator><![CDATA[Jonathan Zweig]]></dc:creator><pubDate>Mon, 13 Feb 2017 00:48:00 GMT</pubDate><content:encoded><![CDATA[<p>Work on my own site has commenced!</p>

<p>Expect to see the site in flux as I gradually add more content.</p>]]></content:encoded></item><item><title><![CDATA[Why Write?]]></title><description><![CDATA[<p>For the longest time, I've refused to write a blog. What do I have to say that's worth a random person reading?</p>

<p>I've changed my views, slightly.</p>]]></description><link>https://jzweig.com/blog/why-write-2/</link><guid isPermaLink="false">b682adf4-c821-4c0f-aa33-b4d40aa403fc</guid><dc:creator><![CDATA[Jonathan Zweig]]></dc:creator><pubDate>Sun, 12 Feb 2017 23:59:42 GMT</pubDate><content:encoded><![CDATA[<p>For the longest time, I've refused to write a blog. What do I have to say that's worth a random person reading?</p>

<p>I've changed my views, slightly.</p>]]></content:encoded></item></channel></rss>