- DokkuZola2020-05-20T00:00:00+00:00https://www.fullstackstanley.com/tags/dokku/atom.xmlHow to deploy a Crystal Lucky application with Dokku on Ubuntu 18.042020-05-20T00:00:00+00:002020-05-20T00:00:00+00:00https://www.fullstackstanley.com/articles/how-to-deploy-a-crystal-lucky-application-with-dokku-on-ubuntu-18-04/<p>This tutorial will show how to set up an app written in the Crystal web framework <a href="https://luckyframework.org">Lucky</a> with Dokku on Ubuntu 18.04. </p>
<span id="continue-reading"></span>
<p>You can run this setup on most low-end boxes, e.g. a $5 Digital Ocean droplet, or in my case, a $2.50 <a href="https://www.hetzner.de/cloud">Hetzner Cloud Server</a>.</p>
<p>By the end of the tutorial you'll know how to deploy your own Lucky apps and be able to manage them easily all on one server.</p>
<h3 id="what-is-lucky">What is Lucky?</h3>
<p>Lucky is a web framework written in <a href="https://crystal-lang.org/">Crystal</a>. Crystal is a programming language with syntax inspired by Ruby but with speeds similar to that of C.</p>
<h3 id="what-is-dokku">What is Dokku?</h3>
<p>Dokku is a small PaaS service powered by Docker that you can run on your own servers. Think of it as a self-hosted command-line <a href="https://www.heroku.com/">Heroku</a>.</p>
<h2 id="prequisites">Prequisites</h2>
<ul>
<li>Crystal 0.34.0 installed locally</li>
<li>A fresh Lucky application installed and running locally.</li>
<li>Basic knowledge of Git.</li>
<li>A server with <a href="http://dokku.viewdocs.io/dokku/getting-started/installation/#installing-the-latest-stable-version">Dokku Installed</a> using Ubuntu 18.04.</li>
<li>A domain or subdomain to point to the server.</li>
</ul>
<p>You'll need a Lucky app to deploy. If you don't have one then no problem! A fresh Lucky app comes with several goodies out of the box, a home page and an authentication system linked to a database. This is more than enough to work with. See <a href="https://luckyframework.org/guides/getting-started/installing">Getting Started</a> and <a href="https://luckyframework.org/guides/getting-started/starting-project">Starting a Lucky Project</a>. Make sure you have the project commited to git and ready for the first deployment.</p>
<h2 id="step-1-setting-up-the-dokku-configuration">Step 1 - Setting up the Dokku configuration</h2>
<p>SSH into your server to get it ready for deployment.</p>
<pre style="background-color:#2b303b;color:#c0c5ce;"><code><span>ssh root@ip
</span></code></pre>
<p>In the following commands replace <code>app.example.com</code> with your domain or subdomain. Replace <code>exampledb</code> with your preferred database name.</p>
<p>This will create the initial app container in Dokku, create the database, and link them both together. The last three lines set environment variables for the Lucky app. The first will tell Lucky to run the app in <code>production</code> mode, the second will tell Lucky what the app URL is, and the third will tell the app to run on port 5000 which Dokku will connect with Nginx to expose to the world.</p>
<pre style="background-color:#2b303b;color:#c0c5ce;"><code><span>dokku apps:create app.example.com
</span><span>dokku postgres:create exampledb
</span><span>dokku postgres:link exampledb app.example.com
</span><span>dokku config:set app.example.com LUCKY_ENV=production
</span><span>dokku config:set app.example.com APP_DOMAIN=app.example.com
</span><span>dokku config:set app.example.com PORT=5000
</span></code></pre>
<p>There's a few more configuration details that need to be set. First, you'll need to tell Lucky the database details that are set in Dokku. Run the below command to get the database URL.</p>
<pre style="background-color:#2b303b;color:#c0c5ce;"><code><span>dokku postgres:info exampledb
</span></code></pre>
<p>Set the <code>DATABASE_URL</code> environment variable from the above output.</p>
<pre style="background-color:#2b303b;color:#c0c5ce;"><code><span>dokku config:set app.example.com DATABASE_URL=postgres://...
</span></code></pre>
<p>Next, Lucky needs a secret key environment variable. In your app directory on your local machine run the following command which will generate a secure key.</p>
<pre style="background-color:#2b303b;color:#c0c5ce;"><code><span>lucky gen.secret_key
</span></code></pre>
<p>Then, back on your remote Dokku server add it to the <code>SECRET_KEY_BASE</code> environment variable.</p>
<pre style="background-color:#2b303b;color:#c0c5ce;"><code><span>dokku config:set app.example.com SECRET_KEY_BASE=...
</span></code></pre>
<p>If you're planning to send emails through the app you'll also need to set <code>SEND_GRID_KEY</code> key, otherwise, change <code>config/email.cr</code> to use <code>Carbon::DevAdapter.new</code> in production (and make sure to commit!)</p>
<pre style="background-color:#2b303b;color:#c0c5ce;"><code><span>dokku config:set app.example.com SEND_GRID_KEY=...
</span></code></pre>
<p>Your server is almost ready for deployment. If you're using a server with 2GB of RAM or less, you'll need to set up a Swap. Without it the deployment process will most likely run into memory issues. <a href="https://www.digitalocean.com/community/tutorials/how-to-add-swap-space-on-ubuntu-18-04">Checkout this tutorial for setting up a Swap</a>. A 1G Swap should be more than enough.</p>
<h2 id="step-2-ready-the-app-for-deployment">Step 2 - Ready the app for deployment</h2>
<p>Back in your local app add a new file called <code>.buildpacks</code> with the following contents</p>
<pre style="background-color:#2b303b;color:#c0c5ce;"><code><span>https://github.com/heroku/heroku-buildpack-nodejs
</span><span>https://github.com/luckyframework/heroku-buildpack-crystal
</span></code></pre>
<h2 id="step-3-deploy">Step - 3 Deploy</h2>
<p>Make a new commit. Finally you're ready to deploy. Run the following commands locally. The first will add your server as a remote origin for your git repo. The second will push the code to the server.</p>
<pre style="background-color:#2b303b;color:#c0c5ce;"><code><span>git remote add dokku dokku@ip:app.example.com
</span><span>git push dokku master
</span></code></pre>
<h2 id="step-4-set-up-ssl">Step 4 - Set up SSL</h2>
<p>Dokku lets you easily set up a Lets Encrypt SSL certificate. Run the following commands to do so</p>
<pre data-lang="bash" style="background-color:#2b303b;color:#c0c5ce;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#bf616a;">dokku</span><span> config:set</span><span style="color:#bf616a;"> --no-restart</span><span> app.example.com DOKKU_LETSENCRYPT_EMAIL=your.email@example.com
</span><span style="color:#bf616a;">dokku</span><span> letsencrypt app.example.com
</span></code></pre>
Deploying a CraftCMS website with Dokku2019-09-06T00:00:00+00:002019-09-06T00:00:00+00:00https://www.fullstackstanley.com/articles/deploying-a-craftcms-website-with-dokku/<p>I recently set up my personal blog with Craft CMS and wanted to host it on my own server. To make the most of my own servers, I tend to run web applications using Dokku. This blog post goes through the details of the process of doing so for your own projects.</p>
<span id="continue-reading"></span><h2 id="what-is-dokku">What is Dokku?</h2>
<p>Dokku is a small PaaS service powered by Docker that you can run on your own servers. Think of it as a self-hosted command-line Heroku.</p>
<p>It's great when you want to host multiple small projects on one server for cheap. Although it's unlikely you'll beat Heroku's free tier on price, it definitely beats the $9 tier for small projects. Your website won't go to sleep when idle, you can set up SSL (quite easily, too), and as mentioned above you can you can host multiple websites all on the same server.</p>
<p>In general, the advantage of Dokku over a standard server is that if you're projects use different versions of the same dependences, e.g. one project is on PHP 7.3 and another on 7.2, Dokku (and Docker) makes this super easy to do.</p>
<p>The other great benefits of Dokku include:</p>
<ul>
<li>Heroku-like git push deployment.</li>
<li>Compatible with Heroku buildpacks.</li>
<li>Easy to setup and link databases, storage, cache, etc to your app.</li>
<li>Requires very little to get started - a $5 DO instance will work fine for multiple small applications.</li>
</ul>
<p>For more information and for installation see the <a href="dokku.viewdocs.io/dokku/">Dokku guides</a>. The rest of this tutorial assumes you have Dokku installed on a server and are able to SSH into the server to run commands. Also, that you have a CraftCMS application in a Git repo ready to deploy.</p>
<h2 id="what-is-craftcms">What is CraftCMS?</h2>
<p>If you're reading this theres a good chance you already know what CraftCMS is. If you've come accross this article by chance and don't know: CraftCMS is a fantastic Content Management System. It's built with modern tools including PHP 7, Twig, and the Yii framework. It's easy to make plugins, and it's ridiculously effective for scaffolding admin areas quickly. </p>
<p>All you really need to concentrate on is integrating your design into the front end. And even then, with Twig, it's a really enjoyable developer experience. </p>
<h2 id="making-your-craftcms-project-dokku-ready">Making your CraftCMS project Dokku-ready</h2>
<p>Update your <code>composer.json</code> file and add the following.</p>
<pre data-lang="diff" style="background-color:#2b303b;color:#c0c5ce;" class="language-diff "><code class="language-diff" data-lang="diff"><span> require: {
</span><span style="color:#a3be8c;">+ "php": "~7.2.0",
</span><span style="color:#a3be8c;">+ ext-gd: *,
</span><span> // ...
</span><span> },
</span><span> extra: {
</span><span style="color:#a3be8c;">+ heroku: {
</span><span style="color:#a3be8c;">+ "document-root": "web",
</span><span style="color:#a3be8c;">+ compile: [
</span><span style="color:#a3be8c;">+ chmod 755 storage
</span><span style="color:#a3be8c;">+ ]
</span><span style="color:#a3be8c;">+ }
</span><span> }
</span></code></pre>
<p>We need to specify the PHP version so Dokku knows which one to use. CraftCMS also requires the GD library or Imagick for image editing.</p>
<p>Set the document root to <code>web</code> and also set the correct permissions for any directories that deal with uploads.</p>
<p>Add a new file called <code>Procfile</code> in the root of your application.</p>
<pre style="background-color:#2b303b;color:#c0c5ce;"><code><span>web: vendor/bin/heroku-php-nginx -C nginx.conf.d/nginx.conf web
</span></code></pre>
<p>This lets us add our own custom nginx configuration.</p>
<p>Add the nginx configuration file to <code>nginx.conf.d/nginx.conf</code></p>
<pre style="background-color:#2b303b;color:#c0c5ce;"><code><span> index index.html index.htm index.php;
</span><span>
</span><span> location ^~ /admin {
</span><span> try_files $uri $uri/ /index.php?$query_string;
</span><span> }
</span><span> location ^~ /cpresources {
</span><span> try_files $uri $uri/ /index.php?$query_string;
</span><span> }
</span><span> location / {
</span><span>
</span><span> gzip on;
</span><span> gzip_min_length 1100;
</span><span> gzip_buffers 4 32k;
</span><span> gzip_types text/css text/javascript text/xml text/plain text/x-component application/javascript application/x-javascript application/json application/xml application/rss+xml font/truetype application/x-font-ttf font/opentype application/vnd.ms-fontobject image/svg+xml;
</span><span> gzip_vary on;
</span><span> gzip_comp_level 6;
</span><span>
</span><span> try_files $uri $uri/ /index.php?$query_string;
</span><span> }
</span><span>
</span><span> error_page 400 401 402 403 405 406 407 408 409 410 411 412 413 414 415 416 417 418 420 422 423 424 426 428 429 431 444 449 450 451 /400-error.html;
</span><span> location /400-error.html {
</span><span> root /var/lib/dokku/data/nginx-vhosts/dokku-errors;
</span><span> internal;
</span><span> }
</span><span>
</span><span> error_page 404 /404-error.html;
</span><span> location /404-error.html {
</span><span> root /var/lib/dokku/data/nginx-vhosts/dokku-errors;
</span><span> internal;
</span><span> }
</span><span>
</span><span> error_page 500 501 502 503 504 505 506 507 508 509 510 511 /500-error.html;
</span><span> location /500-error.html {
</span><span> root /var/lib/dokku/data/nginx-vhosts/dokku-errors;
</span><span> internal;
</span></code></pre>
<p>Now to tell Dokku which buildpacks to use, create a <code>.buildpacks</code> file in the project root as well with the following content.</p>
<pre style="background-color:#2b303b;color:#c0c5ce;"><code><span>https://github.com/heroku/heroku-buildpack-php
</span></code></pre>
<p>That's pretty much it for the CraftCMS side of things. I'd also advise setting up either S3 or Google Cloud Storage for media uploads, this takes out the pain of worrying about persistent storage.</p>
<h2 id="configuring-dokku">Configuring Dokku</h2>
<p>On your server, create the app with the domain name of your choice</p>
<pre data-lang="bash" style="background-color:#2b303b;color:#c0c5ce;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#bf616a;">dokku</span><span> apps:create <yourdomainname.com>
</span></code></pre>
<p>set up a Postgres Database (Or MySQL if you prefer) and link it to the app</p>
<pre data-lang="bash" style="background-color:#2b303b;color:#c0c5ce;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#bf616a;">sudo</span><span> dokku plugin:install https://github.com/dokku/dokku-postgres.git postgres
</span><span style="color:#bf616a;">dokku</span><span> postgres:create <databasename>
</span><span style="color:#bf616a;">dokku</span><span> postgres:link <databasename> <yourdomainname.com>
</span></code></pre>
<p>Run <code>dokku postgres:info databasename</code> to get the database credentials. We'll need to parse the URL in the following format, and add environment variables for each.</p>
<pre style="background-color:#2b303b;color:#c0c5ce;"><code><span>dokku postgres:info <databasename>
</span><span># Dsn: postgres://<USERNAME>:<PASSWORD>@<SERVER>:5432/<DATABASE>
</span><span>dokku config:set <yourdomainname.com> ENVIRONMENT=production
</span><span>dokku config:set <yourdomainname.com> SECURITY_KEY=YOUR_CRAFT_SECURITY_KEY
</span><span>dokku config:set <yourdomainname.com> DB_DRIVER=pgsql
</span><span>dokku config:set <yourdomainname.com> DB_SERVER=<databasename>
</span><span>dokku config:set <yourdomainname.com> DB_USER=<USERNAME>
</span><span>dokku config:set <yourdomainname.com> DB_PASSWORD=<PASSWORD>
</span><span>dokku config:set <yourdomainname.com> DB_DATABASE=<DATABASE>
</span><span>dokku config:set <yourdomainname.com> DB_PORT=5432
</span><span>dokku config:set <yourdomainname.com> DB_SCHEMA=public
</span><span>dokku config:set <yourdomainname.com> DB_TABLE_PREFIX=
</span></code></pre>
<p>Note that, you should double check that these env variables are called from within your Craft config files.</p>
<p>If you require permanent storage on the server (e.g. No S3 or GCS) then you can set that up using <code>storage:mount</code>.</p>
<pre data-lang="bash" style="background-color:#2b303b;color:#c0c5ce;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#65737e;"># optional permanent storage set up
</span><span style="color:#bf616a;">dokku</span><span> storage:mount <yourdomainname.com>/var/lib/dokku/data/storage/<anyuniqueidentifier>:/app/storage
</span></code></pre>
<h2 id="first-deploy">First deploy</h2>
<p>If you have content and users already set up on your local which you wish to migrate to production. You're best bet is to use a tool such as <a href="https://tableplus.com">TablePlus</a> or <a href="https://sequelpro.com/">Sequel Pro</a> to connect directly to the database (Use the Postgres Credentials you have found from the above commands and use SSH to connect directly to it). Dump your local tables and content and import the database to the remote database. Double check your <code>sites</code> table and if your domain is hardcoded to the <code>baseUrl</code>. If it is, then update it to the live domain.</p>
<p>If you don't want to do this and would rather start afresh, you can instead SSH into the app and run <code>./craft setup</code> from within the app after your first deploy. You can do this with <code>dokku run <yourdomainname.com> bash</code> and then <code>cd</code> into the <code>app</code> directory.</p>
<p>In your local project you need to add a new git remote location with the credentials for your server. After that you can push!</p>
<pre data-lang="bash" style="background-color:#2b303b;color:#c0c5ce;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#bf616a;">git</span><span> remote add dokku dokku@serverip:domainname
</span><span style="color:#bf616a;">git</span><span> push dokku master
</span></code></pre>
<p>Hopefully if all went well you should see the set up page for Craft (Or your website if you've imported the database) when you try to access the website. This is assuming you've pointed your domain to the server.</p>
<h2 id="syncing-updates">Syncing updates</h2>
<p>If, like me, you prefer to restrict settings changes on the live site so that they are kept in sync with your git repo, make sure your <code>config/app.php</code> has the following settings.</p>
<pre data-lang="php" style="background-color:#2b303b;color:#c0c5ce;" class="language-php "><code class="language-php" data-lang="php"><span>
</span><span>'*' => [
</span><span> // ...
</span><span> 'useProjectConfigFile' => true,
</span><span> // ...
</span><span>],
</span><span>'production' => [
</span><span> // ...
</span><span> 'allowAdminChanges' => false,
</span><span> // ...
</span><span>]
</span></code></pre>
<p>You'll also want to add this Dokku hook so that the Project YAML file is synced automatically. This prevents your site from going down everytime you push an update while it waits for you to sync settings from the admin.</p>
<pre data-lang="json" style="background-color:#2b303b;color:#c0c5ce;" class="language-json "><code class="language-json" data-lang="json"><span style="color:#65737e;">// app.json
</span><span>{
</span><span> "</span><span style="color:#a3be8c;">scripts</span><span>": {
</span><span> "</span><span style="color:#a3be8c;">dokku</span><span>": {
</span><span> "</span><span style="color:#a3be8c;">postdeploy</span><span>": "</span><span style="color:#a3be8c;">./craft project-config/sync</span><span>"
</span><span> }
</span><span> }
</span><span>}
</span></code></pre>
<p>And that's it! Save, Commit, Push and updates should just work!</p>
<h2 id="ssl">SSL</h2>
<p>If you're using CloudFlare then SSL should just work out of the box. If not, Dokku has commands for setting up AutoSSL which you can find here: http://dokku.viewdocs.io/dokku/configuration/ssl/</p>
<h2 id="closing-thoughts">Closing thoughts</h2>
<p>It took quite some time for me to set this up this correctly. Now that I have the configuration for it deploying updates with Dokku is incredibly easy. I've been running this set up with Google Cloud Storage for media for a few weeks now with no issues. I hope this guide will help others who also want a similar set up!</p>
Using Middleman with Dokku - Updated2018-01-31T00:00:00+00:002018-01-31T00:00:00+00:00https://www.fullstackstanley.com/articles/using-middleman-with-dokku-updated/<p>In a previous blog post I explained how to set up a Middleman blog alongside Dokku. Since then I’ve found a better approach which uses <code>middleman-deploy</code>.</p>
<span id="continue-reading"></span>
<p>Full credit to this <a href="https://github.com/dokku/dokku/issues/1427">Github thread</a> which pointed me to the right path.</p>
<p>First add your new Dokku app on your server the same way you’d set up any Dokku app.</p>
<pre data-lang="bash" style="background-color:#2b303b;color:#c0c5ce;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#bf616a;">dokku</span><span> apps:create example-url.com
</span></code></pre>
<p>In your local version add middleman deploy to your Gemfile</p>
<p><a href="https://github.com/middleman-contrib/middleman-deploy">https://github.com/middleman-contrib/middleman-deploy</a></p>
<p>Use these settings in your <code>confir.rb</code></p>
<pre data-lang="ruby" style="background-color:#2b303b;color:#c0c5ce;" class="language-ruby "><code class="language-ruby" data-lang="ruby"><span>activate </span><span style="color:#a3be8c;">:deploy </span><span style="color:#b48ead;">do </span><span>|</span><span style="color:#bf616a;">deploy</span><span>|
</span><span> deploy.deploy_method = </span><span style="color:#a3be8c;">:git
</span><span> deploy.remote = '</span><span style="color:#a3be8c;">dokku@<serverip>:example-url.com</span><span>'
</span><span> deploy.branch = '</span><span style="color:#a3be8c;">master</span><span>'
</span><span style="color:#b48ead;">end
</span></code></pre>
<p>Note that in Middleman v3 you should use <code>method</code> and in v4 you should use <code>deploy_method</code></p>
<p>Make sure to add Dokku as a remote git on your local Middleman project</p>
<pre data-lang="bash" style="background-color:#2b303b;color:#c0c5ce;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#bf616a;">git</span><span> remote add dokku dokku@<serverip>:example-url.com
</span></code></pre>
<p>In the <code>source</code> dir add these two files</p>
<p><code>Procfile</code></p>
<pre style="background-color:#2b303b;color:#c0c5ce;"><code><span>web: vendor/bin/heroku-php-nginx -C nginx.conf
</span></code></pre>
<p><code>composer.json</code></p>
<pre style="background-color:#2b303b;color:#c0c5ce;"><code><span>{}
</span></code></pre>
<p>Running build will then put both files in the <code>build</code> which is where Dokku will find them.</p>
<p>To deploy, simply commit to git and run </p>
<pre data-lang="bash" style="background-color:#2b303b;color:#c0c5ce;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#bf616a;">Bundle</span><span> exec middleman deploy
</span></code></pre>
<p>That's all there is to it. Except perhaps one caveat!</p>
<pre data-lang="bash" style="background-color:#2b303b;color:#c0c5ce;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#bf616a;">Can</span><span>'</span><span style="color:#a3be8c;">t deploy! Please add a remote with the name </span><span>'</span><span style="color:#bf616a;">dokku@</span><span><serverip>:example-url.com'</span><span style="color:#a3be8c;"> to your repo
</span></code></pre>
<p>There are a couple of issues at play here, and it's to do with the middleman-deploy gem. Here's the quick fix:</p>
<p>You will need to modify the gem code, do this either by using a <code>git clone</code>, and setting the <code>path:</code> in your Gemfile to your local version. Or (and not recommended) use <code>bundle show middleman-deploy</code> to get the gem location on your computer.</p>
<p>In the file named <code>lib/middleman-deploy/strategies/git/force_push.rb</code> comment out these lines</p>
<pre data-lang="ruby" style="background-color:#2b303b;color:#c0c5ce;" class="language-ruby "><code class="language-ruby" data-lang="ruby"><span style="color:#b48ead;">unless</span><span> remote =~/</span><span style="color:#96b5b4;">\.git$</span><span>/
</span><span> url = `</span><span style="color:#a3be8c;">git config --get remote.</span><span>#{url}</span><span style="color:#a3be8c;">.url</span><span>`
</span><span style="color:#b48ead;">end
</span></code></pre>
<p>If your using the name 'dokku' instead of the full remote url in the <code>config.rb</code>, change the remote from <code>dokku</code> to the full git remote address.</p>
<p>Alternatively to modifying the <code>middleman-deploy</code> code, you can name your dokku project ending with <code>.git</code>.</p>
Using Middleman with Dokku2016-08-20T00:00:00+00:002016-08-20T00:00:00+00:00https://www.fullstackstanley.com/articles/using-middleman-with-dokku/<p>I Recently started using Dokku for my websites, which has been great for using various versions of languages and frameworks and keeping different versions of dependencies separate.</p>
<span id="continue-reading"></span>
<p>I wanted to host my blog - which is a static site built with <a href="https://middlemanapp.com">Middleman</a> - on the same server and came accross <a href="http://thepugautomatic.com/2016/01/static-sites-alongside-dokku-on-digital-ocean/">this article</a> which I feel is the perfect solution for most static sites, but I needed to add on to it for my own convenience with Middleman.</p>
<p>There's the option of using the <a href="https://github.com/middleman-contrib/middleman-deploy">middleman-deploy</a> gem, but since there is a fair amount of issues with this gem I decided to try an alternate solution.</p>
<p>As with the previously linked article mentioned, I have made a separate nginx configuration slightly modified to work with Middleman's pretty URL option.</p>
<p>In my <code>/etc/nginx/conf.d/static.conf</code> file I have the following:</p>
<pre style="background-color:#2b303b;color:#c0c5ce;"><code><span>server {
</span><span> server_name ~^(?<domain>.+)$;
</span><span> root /home/static/sites/$domain;
</span><span> index index.html index.htm;
</span><span> location / {
</span><span> try_files $uri $uri/ =404;
</span><span> # this makesure pretty urls works with html files without the extension
</span><span> default_type "text/html";
</span><span> add_header X-Frame-Options SAMEORIGIN;
</span><span> }
</span><span> location ~ /\.git {
</span><span> deny all;
</span><span> }
</span><span>
</span><span> access_log /var/log/nginx/$domain-static-access.log;
</span><span>
</span><span> # error_log can't contain variables, so we'll have to share: http://serverfault.com/a/644898
</span><span> error_log /var/log/nginx/static-error.log;
</span><span>}
</span></code></pre>
<p>I made sure my build directory is included in git and then pushed it to Github as a subtree.</p>
<pre data-lang="bash" style="background-color:#2b303b;color:#c0c5ce;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#bf616a;">git</span><span> subtree push</span><span style="color:#bf616a;"> --prefix</span><span> build origin production
</span></code></pre>
<p>In my <code>static</code> website directory on my server I clone the repository and switch to production.</p>
<pre data-lang="bash" style="background-color:#2b303b;color:#c0c5ce;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#bf616a;">git</span><span> clone git@github.com:username/example.git
</span><span style="color:#bf616a;">git</span><span> checkout production
</span></code></pre>
<p>Below is an example of commands I can use to push changes up to production!</p>
<pre data-lang="bash" style="background-color:#2b303b;color:#c0c5ce;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#65737e;"># Your usual git commit workflow
</span><span style="color:#bf616a;">middleman</span><span> build
</span><span style="color:#bf616a;">git</span><span> add .
</span><span style="color:#bf616a;">git</span><span> commit</span><span style="color:#bf616a;"> -m </span><span>"</span><span style="color:#a3be8c;">your commit</span><span>"
</span><span style="color:#bf616a;">git</span><span> push origin master
</span><span style="color:#65737e;"># Push update to the production build subtree
</span><span style="color:#bf616a;">git</span><span> subtree push</span><span style="color:#bf616a;"> --prefix</span><span> build origin production
</span><span style="color:#65737e;"># SSH into your server, change into the repo directory and run git pull
</span><span style="color:#96b5b4;">echo </span><span>"</span><span style="color:#a3be8c;">cd sites/example.com && git pull</span><span>" | </span><span style="color:#bf616a;">ssh</span><span> static@example.com /bin/bash
</span></code></pre>
<p>After restarting nginx with <code>sudo service nginx restart</code> everything should work!</p>