<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Marc</title>
    <description>The latest articles on DEV Community by Marc (@webdevchallenges).</description>
    <link>https://dev.to/webdevchallenges</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F89896%2F76565870-8be3-42c1-95f9-2989681c542e.png</url>
      <title>DEV Community: Marc</title>
      <link>https://dev.to/webdevchallenges</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/webdevchallenges"/>
    <language>en</language>
    <item>
      <title>How my blog got almost perfect lighthouse results</title>
      <dc:creator>Marc</dc:creator>
      <pubDate>Sun, 06 Jun 2021 11:59:23 +0000</pubDate>
      <link>https://dev.to/webdevchallenges/how-my-blog-got-almost-perfect-lighthouse-results-3gdl</link>
      <guid>https://dev.to/webdevchallenges/how-my-blog-got-almost-perfect-lighthouse-results-3gdl</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwebdevchallenges.com%2Fuploads%2Ffile_upload%2Fimage%2F19%2Fimage.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwebdevchallenges.com%2Fuploads%2Ffile_upload%2Fimage%2F19%2Fimage.png" alt="my blog's lighthouse results"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lighthouse is an open source tool that is integrated in the chrome browser per default. If you open up your developer tools (F12) you will see a tab “Lighthouse” which lets you generate a report for the current page you are on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://webdevchallenges.com/" rel="noopener noreferrer"&gt;My Blog&lt;/a&gt; has a performance rating of &lt;strong&gt;99&lt;/strong&gt; which is not easy to reach. Lets compare that to the “simpleprogrammer” blog which has a &lt;strong&gt;77&lt;/strong&gt; percent performance rating in lighthouse.&lt;/p&gt;

&lt;p&gt;The performance rating is calculated by a few factors like “First Contentful Paint”, “Largest Contentful Paint”, “Time to Interactive” and so on. Most of these indicators depend on the amount of files your site loads for example Images, JavaScript files, CSS files and so on. The less the better. Then it also depends on how big these files are. If you have megabytes of data that need to be loaded in order for your page to render, that will decrease the performance heavily.&lt;/p&gt;

&lt;p&gt;As you can see, my blog only makes 11 requests and only transfers 80 kilobytes of data for a blog post to load. (Unless the blog post includes images obviously)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwebdevchallenges.com%2Fuploads%2Ffile_upload%2Fimage%2F22%2Fimage.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwebdevchallenges.com%2Fuploads%2Ffile_upload%2Fimage%2F22%2Fimage.png" alt="my blog's network requests"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Compare that to the 71 requests and 887 kilobytes of data transferred in order to load the “simpleprogrammer blog”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwebdevchallenges.com%2Fuploads%2Ffile_upload%2Fimage%2F23%2Fimage.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwebdevchallenges.com%2Fuploads%2Ffile_upload%2Fimage%2F23%2Fimage.png" alt="simpleprogrammer's network requests"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can read more about the performance scoring &lt;a href="https://web.dev/performance-scoring/?utm_source=lighthouse&amp;amp;utm_medium=devtools" rel="noopener noreferrer"&gt;on the official documentation&lt;/a&gt; if you are interested.&lt;/p&gt;

&lt;h2&gt;
  
  
  Best practices
&lt;/h2&gt;

&lt;p&gt;There are many best practice checks in lighthouse which you can see once you generate a report. One of them is serving your page via HTTPS. My blog is built with Rails and uses the Puma web server which then gets served via NGINX. I use LetsEncrypt for free SSL certificates. As you can see, a &lt;a href="https://www.ssllabs.com/ssltest/" rel="noopener noreferrer"&gt;SSL Labs&lt;/a&gt; test gives my blog an “A” rating.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwebdevchallenges.com%2Fuploads%2Ffile_upload%2Fimage%2F20%2Fimage.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwebdevchallenges.com%2Fuploads%2Ffile_upload%2Fimage%2F20%2Fimage.png" alt="my blog's ssl lab test results"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This test checks if your site implements SSL correctly and makes sure that your webserver doesn’t use weak or outdated standards.&lt;/p&gt;

&lt;h2&gt;
  
  
  Long story short
&lt;/h2&gt;

&lt;p&gt;Long story short, my blog is a custom built rails application that has almost no bloat in it unlike many wordpress blogs. I use plain JavaScript and very little of that. I use &lt;a href="https://webdevchallenges.com/add-tailwind-to-rails" rel="noopener noreferrer"&gt;Tailwind CSS 2.0&lt;/a&gt; with the purge function which reduces the CSS bundle to only &lt;strong&gt;16.8 kilobytes&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;One thing I might need to improve in the future depending on if someone reads my posts and if they life far away from the location of the server hosting my blog is implementing a CDN like &lt;a href="https://aws.amazon.com/de/cloudfront/" rel="noopener noreferrer"&gt;Amazon’s Cloudfront&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>lighthouse</category>
      <category>rails</category>
      <category>https</category>
      <category>performance</category>
    </item>
    <item>
      <title>A nice default button CSS animation</title>
      <dc:creator>Marc</dc:creator>
      <pubDate>Fri, 04 Jun 2021 13:45:40 +0000</pubDate>
      <link>https://dev.to/webdevchallenges/a-nice-default-button-css-animation-jl7</link>
      <guid>https://dev.to/webdevchallenges/a-nice-default-button-css-animation-jl7</guid>
      <description>&lt;p&gt;Whenever I create a new project and I want to keep it lightweight without adding any component libraries and so on, I just fiddle together some styles for a button but I rarely take the time to make it look really nice and responsive.&lt;/p&gt;

&lt;p&gt;So I spent 15 minutes in creating a button style which looks nice in my opinion. If you like it too, feel free to use it in your project! This is how it looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwebdevchallenges.com%2Fuploads%2Ffile_upload%2Fimage%2F21%2Foutput.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwebdevchallenges.com%2Fuploads%2Ffile_upload%2Fimage%2F21%2Foutput.gif" alt="image"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;style&amp;gt;
  button {
    background-color: rgb(37, 99, 235);
    font-weight: bold;
    color: white;
    padding: 10px 16px;
    font-size: 1rem;
    border-radius: .5rem;
    transition: all .15s cubic-bezier(0.4,0,0.2,1);
    border: none;
    cursor: pointer;
  }

  button:hover {
    background-color: rgb(29,78,216);
    box-shadow: 0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23);
  }

  button:active {
    position: relative;
    top: 1px;
    right: 1px;
    box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23);
  }
&amp;lt;/style&amp;gt;

&amp;lt;div style="margin: 6rem;"&amp;gt;
  &amp;lt;button&amp;gt;Click me&amp;lt;/button&amp;gt;
&amp;lt;/div&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First some general rules, deep blue background, white bold font, padding, rounded corners, no border and pointer cursor.&lt;/p&gt;

&lt;p&gt;Next a hover effect which makes the background color a little darker and adds a box shadow which makes it look like the button elevates up a little bit.&lt;/p&gt;

&lt;p&gt;Lastly an active state that does two things in order to make it look like you actually press that button down:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It changes the position slightly towards the bottom left&lt;/li&gt;
&lt;li&gt;It reduces the box shadow we set earlier in the hover effect&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That way it looks like it is less elevated i.e. pressed down.&lt;/p&gt;

</description>
      <category>css</category>
      <category>button</category>
    </item>
    <item>
      <title>How to add a RSS feed to a rails blog</title>
      <dc:creator>Marc</dc:creator>
      <pubDate>Thu, 03 Jun 2021 12:32:22 +0000</pubDate>
      <link>https://dev.to/webdevchallenges/how-to-add-a-rss-feed-to-a-rails-blog-3mgf</link>
      <guid>https://dev.to/webdevchallenges/how-to-add-a-rss-feed-to-a-rails-blog-3mgf</guid>
      <description>&lt;p&gt;&lt;a href="https://developer.apple.com/news/rss/news.rss"&gt;RSS Feeds&lt;/a&gt; are publicly accessible URLs of websites that can be consumed by other software in order to utilize the content of a site. If you write posts on your own blog like I do and then want to crosspost your posts to other sites like &lt;a href="https://dev.to"&gt;dev.to&lt;/a&gt;, a RSS feed might be helpful in doing so.&lt;/p&gt;

&lt;p&gt;The RSS feed of my blog is available at &lt;a href="https://webdevchallenges.com/feed"&gt;/feed&lt;/a&gt;. It gets generated dynamically so it always includes my latest posts.&lt;/p&gt;

&lt;h1&gt;
  
  
  How to add a RSS feed with Rails
&lt;/h1&gt;

&lt;p&gt;The way I implemented this RSS feed is very similar to the way I implemented &lt;a href="https://webdevchallenges.com/how-to-add-a-dynamically-generated-sitemap-with-rails"&gt;my Sitemap.xml&lt;/a&gt; first lets add a route to our &lt;code&gt;config/routes.rb&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;get 'feed', to: 'home#feed', format: 'xml', as: :feed

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, it expects to find a controller &lt;code&gt;home&lt;/code&gt; with an action &lt;code&gt;feed&lt;/code&gt;, so either create this controller too yourself or point to a different one in your application. The action itself is empty:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class HomeController &amp;lt; ApplicationController
  def feed
  end
end

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last thing we need is the view file &lt;code&gt;views/home/feed.xml.builder&lt;/code&gt; which generates the xml code. It iterates through published posts, paginates them and then renders XML for each of them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;xml.instruct! :xml, version: "1.0"
xml.rss :version =&amp;gt; "2.0" do
  xml.channel do
    xml.title "WebDevChallenges"
    xml.description "A blog about the lessons learned as a Web Developer"
    xml.link root_url

    Post.published.order('created_at DESC').page(1).each do |post|
      xml.item do
        xml.title post.title
        xml.description post.html_content
        xml.pubDate post.created_at.to_s(:rfc822)
        xml.link show_post_url(post.slug)
        xml.guid show_post_url(post.slug)
      end
    end
  end
end

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As mentioned earlier, some sites like dev.to &lt;a href="https://dev.to/settings/extensions"&gt;offer the possibility to enter your own RSS feed&lt;/a&gt; which then gets fetched regularly. If it detects a new post, it will land in your dashboard as a draft which you then can use to easily release your post there aswell which is exactly what I do.&lt;/p&gt;

&lt;p&gt;Important to note here is that posting your content on multiple platforms might be negative in terms of SEO if google cannot find out which of the websites is the original creator of the content. dev.to offers you the option to set a canonical URL so it won’t affect your SEO negatively. The canonical URL gets set automatically if import your posts via RSS.&lt;/p&gt;

&lt;p&gt;Hope that helped :)&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How to add a dynamically generated sitemap with rails</title>
      <dc:creator>Marc</dc:creator>
      <pubDate>Tue, 01 Jun 2021 21:13:18 +0000</pubDate>
      <link>https://dev.to/webdevchallenges/how-to-add-a-dynamically-generated-sitemap-with-rails-3lkm</link>
      <guid>https://dev.to/webdevchallenges/how-to-add-a-dynamically-generated-sitemap-with-rails-3lkm</guid>
      <description>&lt;p&gt;The &lt;code&gt;sitemap.xml&lt;/code&gt; &lt;a href="https://webdevchallenges.com/sitemap.xml"&gt;file on my blog&lt;/a&gt; is generated dynamically because I want it to include my latest posts in it.&lt;/p&gt;

&lt;p&gt;The way I did that is that in a controller (in my case the &lt;code&gt;HomeController&lt;/code&gt;) I added an action which is empty:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class HomeController &amp;lt; ApplicationController
  def sitemap
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;config/routes.rb&lt;/code&gt; file defines route route and explicitly sets the format:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;get 'sitemap.xml', to: 'home#sitemap', format: 'xml', as: :sitemap
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;app/views/home/sitemap.xml.builder&lt;/code&gt; file then defines some static routes and also defines routes depending on database entries like posts.&lt;br&gt;
These routes simply render the urls of static pages and dynamic ones (posts). Note how you can use the &lt;code&gt;.xmlschema&lt;/code&gt; method on date objects which returns the correct format for sitemaps.&lt;br&gt;
Also we are using the &lt;code&gt;.find_each&lt;/code&gt; &lt;a href="https://apidock.com/rails/ActiveRecord/Batches/ClassMethods/find_each"&gt;method&lt;/a&gt; because if we have a massive amount of posts later, loading them to memory with &lt;code&gt;.each&lt;/code&gt;&lt;br&gt;
might result in problems later.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;xml.instruct! :xml, :version=&amp;gt;"1.0"
xml.tag! 'urlset', 'xmlns' =&amp;gt; 'http://www.sitemaps.org/schemas/sitemap/0.9', 'xmlns:image' =&amp;gt; 'http://www.google.com/schemas/sitemap-image/1.1', 'xmlns:video' =&amp;gt; 'http://www.google.com/schemas/sitemap-video/1.1' do
  xml.url do
    xml.loc root_url
  end
  xml.url do
    xml.loc imprint_and_privacy_policy_url
  end
  xml.url do
    xml.loc impressum_und_datenschutzerklaerung_url
  end

  Post.published.find_each do |post|
    xml.url do
      xml.loc show_post_url(post.slug)
      xml.lastmod post.updated_at.xmlschema
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Make sure your &lt;code&gt;robots.txt&lt;/code&gt; file then points to that sitemap like this for search engines to find that file correctly.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Sitemap: https://webdevchallenges.com/sitemap.xml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
    </item>
    <item>
      <title>How to Deploy a Rails 6 Application with Capistrano, Nginx, Puma, Postgresql, LetsEncrypt on Ubuntu 20.04</title>
      <dc:creator>Marc</dc:creator>
      <pubDate>Mon, 31 May 2021 10:14:11 +0000</pubDate>
      <link>https://dev.to/webdevchallenges/how-to-deploy-a-rails-6-application-with-capistrano-nginx-puma-postgresql-letsencrypt-on-ubuntu-20-04-2dlh</link>
      <guid>https://dev.to/webdevchallenges/how-to-deploy-a-rails-6-application-with-capistrano-nginx-puma-postgresql-letsencrypt-on-ubuntu-20-04-2dlh</guid>
      <description>&lt;h1&gt;
  
  
  What are we going to do
&lt;/h1&gt;

&lt;p&gt;So whenever I start a new project and want to deploy it to production, I need to research from scratch how to setup a Ubuntu Server including Firewall, how to setup Capistrano, get NGINX to work with Puma etc. That’s why I summarize everything I do to get a Project deployed.&lt;/p&gt;

&lt;h1&gt;
  
  
  Create the Rails project
&lt;/h1&gt;

&lt;p&gt;Make sure you have postgresql installed and running locally.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rails -v
# Rails 6.1.3.2
rails new mysite --database=postgresql
rake db:setup
rails db:migrate
rails s

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you should be able to visit &lt;a href="http://localhost:3000"&gt;http://localhost:3000&lt;/a&gt; in your browser.&lt;/p&gt;

&lt;h1&gt;
  
  
  Server Setup
&lt;/h1&gt;

&lt;p&gt;First of all, purchase a Ubuntu 20.04 Server from your favorite host. I always use Hetzner for my Projects. Their servers start at 2,96€ per Month for 1vCPU, 2GB of RAM and a 20GB local SSD.&lt;a href="https://hetzner.cloud/?ref=v1n8s5nlgH4O"&gt;You can use my referral link if you want to check it out too&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  SSH Config
&lt;/h2&gt;

&lt;p&gt;I always make sure to select my public key when I create the server so that one is already entered in the &lt;code&gt;~/.ssh/authorized_keys&lt;/code&gt;file for the root user.&lt;/p&gt;

&lt;p&gt;If you provide an SSH key, Hetzner will automatically disable Password authentication which provides an extra layer of security.&lt;/p&gt;

&lt;p&gt;Make sure your &lt;code&gt;/etc/ssh/sshd_config&lt;/code&gt; file does not allow password authentication (&lt;code&gt;#PasswordAuthentication yes&lt;/code&gt; see the hash at the start of the line).&lt;/p&gt;

&lt;p&gt;If you would need to change that, make sure to restart the ssh daemon afterwards (&lt;code&gt;systemctl restart sshd&lt;/code&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Set the A record
&lt;/h2&gt;

&lt;p&gt;Once you purchased your server, you will receive a IPv4 Address. When you already purchased a domain for your project, make sure to point the A Record of that domain to your newly purchased Server’s IPv4 Address. I always do that before setting up my server because that might take a few minutes to propagate through the DNS Servers.&lt;/p&gt;

&lt;p&gt;This A record needs to be fully propagated once we try to aquire LetsEncrypt certificates later on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Update packages
&lt;/h2&gt;

&lt;p&gt;Run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apt-get update

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to update your packages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Firewall setup
&lt;/h2&gt;

&lt;p&gt;Install ufw (uncomplicated firewall) and allow ssh, http and https.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apt-get install ufw
ufw status
ufw allow ssh
ufw allow http
ufw allow https
ufw enable
ufw status

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Create the rails user
&lt;/h2&gt;

&lt;p&gt;Let’s create a new user called &lt;code&gt;rails&lt;/code&gt; just for running the application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;adduser rails

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create an interactive input for creating the user, set a password and just confirm the rest (ENTER).&lt;/p&gt;

&lt;p&gt;We want to be able to ssh into our rails user. Lets copy our &lt;code&gt;~/.ssh/authorized_keys&lt;/code&gt; file from the root user.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir -p /home/rails/.ssh
cp ~/.ssh/authorized_keys /home/rails/.ssh
chown -R rails:rails /home/rails/.ssh/

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This user needs to be a sudo user in order to restart the puma systemctl service we are going to create later on.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;usermod -aG sudo rails
vi /etc/sudoers
# add the following line at the bottom
# rails ALL=(ALL) NOPASSWD: ALL

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should be able to ssh into your server with the rails user now.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ssh rails@mysite.com

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Install postgres
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apt-get install postgresql postgresql-contrib libpq-dev
su postgres
cd
createdb mysite_production
psql
create user rails with password 'mypassword';
grant all privileges on database mysite_production to rails;
exit # exit psql shell
exit # back to root user

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Install more dependencies
&lt;/h2&gt;

&lt;p&gt;Next we need to install more dependencies&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Node&lt;/li&gt;
&lt;li&gt;Yarn&lt;/li&gt;
&lt;li&gt;RVM&lt;/li&gt;
&lt;li&gt;NGINX&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Node &amp;amp; Yarn
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# see https://github.com/nodesource/distributions/blob/master/README.md
curl -fsSL https://deb.nodesource.com/setup_14.x | sudo -E bash -
apt-get install -y nodejs
node -v
npm install --global yarn
yarn -v

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  RVM
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;su rails
cd
# see https://rvm.io/rvm/install
gpg --keyserver hkp://pool.sks-keyservers.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
curl -sSL https://get.rvm.io | bash -s stable --ruby

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check on your local machine which ruby version is used in your project (3.0.1 for me)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd mysite
cat Gemfile | grep ruby

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then install that same version on the server using RVM.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# as root
/home/rails/.rvm/bin/rvm install ruby-3.0.1
su rails
cd
source ~/.rvm/scripts/rvm
rvm use ruby-3.0.1
rvm use --default ruby-3.0.1
rvm -v
ruby -v

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Install nginx
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apt-get install nginx
systemctl start nginx
systemctl enable nginx

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Install nginx
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apt-get install git

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Install capistrano
&lt;/h1&gt;

&lt;p&gt;Add the following gems to your &lt;code&gt;group :development do&lt;/code&gt; block inside the &lt;code&gt;Gemfile&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gem 'capistrano', require: false
gem 'capistrano-rvm', require: false
gem 'capistrano-rails', require: false
gem 'capistrano-bundler', require: false
gem 'capistrano3-puma', require: false

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install the gems and install cap.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bundle install
cap install

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the following to your &lt;code&gt;Capfile&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
require "capistrano/rails"
require "capistrano/bundler"
require "capistrano/rvm"
require 'capistrano/puma'
install_plugin Capistrano::Puma
install_plugin Capistrano::Puma::Systemd
...

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Adjust your &lt;code&gt;config/deploy.rb&lt;/code&gt; file to look like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;lock "~&amp;gt; 3.16.0"

# replace obvious parts
server 'mysite.com', port: 22, roles: [:web, :app, :db], primary: true
set :application, "mysite"
set :repo_url, "git@github.com:me/mysite.git"

set :user, 'rails'
set :puma_threads, [4, 16]
set :puma_workers, 0

set :pty, true
set :use_sudo, false
set :stage, :production
set :deploy_via, :remote_cache
set :deploy_to, "/home/#{fetch(:user)}/apps/#{fetch(:application)}"
set :puma_bind, "unix://#{shared_path}/tmp/sockets/#{fetch(:application)}-puma.sock"
set :puma_state, "#{shared_path}/tmp/pids/puma.state"
set :puma_pid, "#{shared_path}/tmp/pids/puma.pid"
set :puma_access_log, "#{release_path}/log/puma.access.log"
set :puma_error_log, "#{release_path}/log/puma.error.log"
set :ssh_options, { forward_agent: true, user: fetch(:user), keys: %w(~/.ssh/id_rsa.pub) }
set :puma_preload_app, true
set :puma_worker_timeout, nil
set :puma_init_active_record, true # Change to false when not using ActiveRecord

append :linked_files, "config/master.key"
append :linked_dirs, "log", "tmp/pids", "tmp/cache", "public/uploads"

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Commit and push your changes.&lt;/p&gt;

&lt;p&gt;Copy your &lt;code&gt;master.key&lt;/code&gt; to the shared dir.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ssh rails@mysite.com
mkdir -p apps/mysite/shared/config
# back on your machine
cd mysite
scp config/master.key rails@mysite.com:apps/mysite/shared/config

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Adjust your &lt;code&gt;config/database.yml&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;production:
  &amp;lt;&amp;lt;: *default
  database: mysite_production
  host: localhost
  username: rails
  password: mypassword

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Test a production deploy&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cap production deploy

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are on mac os, you might encounter this error.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Your bundle only supports platforms ["x86_64-darwin-19"] but your local platform is x86_64-linux. Add the current platform to the lockfile with 'bundle lock --add-platform x86_64-linux' and try again.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In that case just run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bundle lock --add-platform x86_64-linux
# commit &amp;amp; push

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Puma systemd service
&lt;/h1&gt;

&lt;p&gt;The deploy should fail in the end with the message &lt;code&gt;Failed to restart puma_mysite_production.service: Unit puma_mysite_production.service not found.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;So let’s create this service.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vi /etc/systemd/system/puma_mysite_production.service

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enter the following&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Unit]
Description=Puma HTTP Server for mysite (production)
After=network.target

[Service]
Type=simple
User=rails
WorkingDirectory=/home/rails/apps/mysite/current
ExecStart=/home/rails/.rvm/bin/rvm default do bundle exec puma -C /home/rails/apps/mysite/shared/puma.rb
ExecReload=/bin/kill -TSTP $MAINPID
StandardOutput=append:/home/rails/apps/mysite/current/log/puma.access.log
StandardError=append:/home/rails/apps/mysite/current/log/puma.error.log
Restart=always
RestartSec=1
SyslogIdentifier=puma

[Install]
WantedBy=multi-user.target

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create the directory for the puma sockets to live in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir apps/mysite/shared/tmp/sockets

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should be able to run the service now.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;systemctl start puma_mysite_production.service
systemctl enable puma_mysite_production.service
systemctl status puma_mysite_production.service

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Try to deploy again, this time it should work fine.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cap production deploy

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  NGINX Setup
&lt;/h1&gt;

&lt;p&gt;We need a webserver to proxy httpp and httpps requests to puma. NGINX does this nicely.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vi /etc/nginx/sites-enabled/mysite

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the following&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;upstream puma {
  server unix:///home/rails/apps/mysite/shared/tmp/sockets/mysite-puma.sock;
}

server {
  server_name mysite.com;

  root /home/rails/apps/mysite/current/public;
  access_log /home/rails/apps/mysite/current/log/nginx.access.log;
  error_log /home/rails/apps/mysite/current/log/nginx.error.log info;

  location ^~ /assets/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
  }

  try_files $uri/index.html $uri @puma;
  location @puma {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-Ssl on; # Optional
    proxy_set_header X-Forwarded-Port $server_port;
    proxy_set_header X-Forwarded-Host $host;

    proxy_redirect off;

    proxy_pass http://puma;
  }

  error_page 500 502 503 504 /500.html;
  client_max_body_size 100M;
  keepalive_timeout 10;
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check if the config is valid &amp;amp; restart nginx.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nginx -t
systemctl restart nginx

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In case you get a permissions error, running the following should fix that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo chown rails:rails -R apps/mysite/

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Adding LetsEncrypt
&lt;/h1&gt;

&lt;p&gt;You should be able to access your page now via http.&lt;/p&gt;

&lt;p&gt;You need SSL Certificates in order to run your site via https. LetsEncrypt is free and easy to setup with nginx.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apt-get install certbot python3-certbot-nginx
certbot --nginx

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Follow the interactive installer, I always choose redirect in the end and you should probably too. Refresh your page, you should be redirect to https now.&lt;/p&gt;

&lt;h1&gt;
  
  
  Debugging
&lt;/h1&gt;

&lt;p&gt;Errors can occurr in a few places here are a few hints:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# check if nginx is running
systemctl status nginx
journalctl -u nginx

# check if puma is running
systemctl status puma_mysite_production.service
journalctl -u puma_mysite_production.service

# application logs
tail -f apps/mysite/current/log/*

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hope you find it useful. Have a nice day ;)&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Add Tailwind 2 to Rails 6.1</title>
      <dc:creator>Marc</dc:creator>
      <pubDate>Sun, 30 May 2021 14:40:13 +0000</pubDate>
      <link>https://dev.to/webdevchallenges/add-tailwind-2-to-rails-6-1-3f5f</link>
      <guid>https://dev.to/webdevchallenges/add-tailwind-2-to-rails-6-1-3f5f</guid>
      <description>&lt;p&gt;Originally posted on my blog: &lt;a href="https://webdevchallenges.com/add-tailwind-to-rails"&gt;https://webdevchallenges.com/add-tailwind-to-rails&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/SWjb8sqcdws"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h1&gt;
  
  
  How to add Tailwind to Rails 6.1
&lt;/h1&gt;

&lt;h2&gt;
  
  
  New Rails Project
&lt;/h2&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rails new myproject
cd myproject
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Install dependencies
&lt;/h2&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add tailwindcss@npm:@tailwindcss/postcss7-compat postcss@7 autoprefixer@9
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Generate tailwind config
&lt;/h2&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx tailwindcss init --full
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Add purge paths to the newly generated file (&lt;code&gt;tailwind.config.js&lt;/code&gt;) to reduce the css file dramatically.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;purge: [
  "./app/**/*.html.erb",
  "./app/helpers/**/*.rb",
  "./app/javascript/**/*.js",
  "./app/javascript/**/*.vue",
],
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Create a scss file for the application
&lt;/h2&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir app/javascript/stylesheets
touch app/javascript/stylesheets/application.scss
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Import some basic tailwind stuff in there&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@import "tailwindcss/base";
@import "tailwindcss/components";
@import "tailwindcss/utilities";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Import that file in &lt;code&gt;app/javascript/packs/application.js&lt;/code&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import "stylesheets/application";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Require tailwindcss in postcss
&lt;/h2&gt;

&lt;p&gt;Add the following require to the &lt;code&gt;postcss.config.js&lt;/code&gt; file&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;require('tailwindcss'),
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Import the tailwind stylesheet pack
&lt;/h2&gt;

&lt;p&gt;Import the stylesheet_pack_tag in your layouts (&lt;code&gt;app/views/layouts/application.html.erb&lt;/code&gt;)&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;%= stylesheet_pack_tag 'application', media: 'all' %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Try it out
&lt;/h2&gt;

&lt;p&gt;Uun the rails server in one terminal&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rails s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;And the webpack dev server in another one&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./bin/webpack-dev-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>tailwindcss</category>
      <category>rails</category>
    </item>
  </channel>
</rss>
