<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><title>alchemmist — Github</title><link>https://alchemmist.xyz/tags/github/</link><description>Последние записи в блоге alchemmist</description><generator>Hugo 0.163.3</generator><language>en</language><atom:link href="https://alchemmist.xyz/tags/github/index.xml" rel="self" type="application/rss+xml"/><lastBuildDate>Tue, 24 Jun 2025 14:18:00 +0300</lastBuildDate><item><title>Transparent Deployment with GitHub Actions</title><link>https://alchemmist.xyz/articles/deploy-gh-actions/</link><pubDate>Tue, 24 Jun 2025 14:18:00 +0300</pubDate><dc:creator>alchemmist</dc:creator><guid>https://alchemmist.xyz/articles/deploy-gh-actions/</guid><description>Recently, find the simple way to make anything at my servers in GitHub pipeline with Actions. And I love it’s very clear. I can control all operations, step and processes. Now I’ll show how to make clear depoly with it, but you can use similar for your goals.
Let’s think! How we deploy manually? In the simple case, we connect to server, pull repository and then restart our app. We want automate all of this. Let’s start with first point. We connect to server with SSH, but what we need to do it? Often connection looks like this:</description><content:encoded><![CDATA[<p>Recently, find the simple way to make anything at my servers in GitHub pipeline with Actions. And I love it’s very clear. I can control all operations, step and processes. Now I’ll show how to make clear depoly with it, but you can use similar for your goals.</p>
<p>Let’s think! How we deploy manually? In the simple case, we connect to server, pull repository and then restart our app.
<img src="/images/deploy-pipeline.svg" class="content-img" style="width:500px" alt="" loading="lazy" decoding="async" />
We want automate all of this. Let’s start with first point. We connect to server with SSH, but what we need to do it? Often connection looks like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">ssh root@192.168.0.1 -i ~/.ssh/id_rsa25519
</span></span></code></pre></div><p>Here i have three information unit for get access:</p>
<ol>
<li>Server IP address</li>
<li>Username of user</li>
<li>SSH private key
We make “clear” deployment, therefore all step in our manually pipeline will be automate. In order to GitHub Actions can connect to our server we need to give all information. GitHub have special entity for it: <code>Secrets and Variables</code> now, for more security we put all to <code>secrets</code>.</li>
</ol>
<p>Open your GitHub repository and go to <code>Settings</code>, here in <code>Security</code> section click to <code>Secrets and Variables</code> and go to <code>Actions</code>. Then we will add three secrets: <code>SSH_USER</code>, <code>SSH_HOST</code>, <code>SSH_KEY</code>.  Remember, the public pair of <code>SSH_KEY</code> private key need to be added to <code>~/.ssh/authorized_keys</code> on server. Nice! First step was finished.</p>
<p>Next we need to pull repository. If your server is clean, you need to firstly clone it. If your repository is private, most likely, when you try to do it, you got something like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-txt" data-lang="txt"><span class="line"><span class="cl">git@github.com: Permission denied (publickey).
</span></span><span class="line"><span class="cl">fatal: Could not read from remote repository.
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">Please make sure you have the correct access rights
</span></span><span class="line"><span class="cl">and the repository exists.
</span></span></code></pre></div><p>You need to generate <em>(or migrate)</em> the ssh keys on your server. For generate you can use this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">ssh-keygen -C github -t ed25519
</span></span></code></pre></div><p>Then copy <code>~/.ssh/id_ed25519.pub</code> and copy on GitHub repository settings at <code>Deploy keys</code>. After you can clone repository. In order to GitHub Actions know where your project we make new secret <code>SSH_PROJECT_PATH</code>.</p>
<p>Last step: GitHub Actions. Restart service or anything steps, what you want, we describe <code>.gitub/workflows/deploy.yaml</code> <em>(file name doesn’t matter)</em>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Deploy</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">on</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">push</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">branches</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">jobs</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">deploy</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">runs-on</span><span class="p">:</span><span class="w"> </span><span class="l">ubuntu-latest</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">steps</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Pull repo</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">appleboy/ssh-action@master</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">with</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">host</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.SSH_HOST }}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">username</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.SSH_USER }}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">key</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.SSH_KEY }}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">script</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">            cd ${{ secrets.SSH_PROJECT_PATH }}
</span></span></span><span class="line"><span class="cl"><span class="sd">            git pull origin main --rebase</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Compose down</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">appleboy/ssh-action@master</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">with</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">host</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.SSH_HOST }}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">username</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.SSH_USER }}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">key</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.SSH_KEY }}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">script</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">            cd ${{ secrets.SSH_PROJECT_PATH }}
</span></span></span><span class="line"><span class="cl"><span class="sd">            docker compose down</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Compose up</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">appleboy/ssh-action@master</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">with</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">host</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.SSH_HOST }}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">username</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.SSH_USER }}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">key</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.SSH_KEY }}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">script</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">            cd ${{ secrets.SSH_PROJECT_PATH }}
</span></span></span><span class="line"><span class="cl"><span class="sd">            docker compose up -d</span><span class="w">
</span></span></span></code></pre></div><p>In this example I’m using docker for restart my services. Choose your way!</p>
]]></content:encoded><category>github</category></item></channel></rss>