<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">

  <channel>
    <title>Self Host on </title>
    <link>https://priyatham.in/en/series/self-host/</link>
    <description>Recent Posts in Self Host on </description>
    <generator>Hugo 0.161.1</generator>
    <language>en-GB</language>
    <managingEditor>Priyatham</managingEditor>
    
      <webMaster>Priyatham</webMaster>
    <lastBuildDate>Sat, 30 May 2026 18:49:16 -0700</lastBuildDate>
    <atom:link href="https://priyatham.in/en/series/self-host/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Code Deployment: The self-hosted way</title>
      <link>https://priyatham.in/en/post/deploy-websites/</link>
      <pubDate>Sun, 12 Apr 2026 00:00:00 +0000</pubDate>
      <author>Priyatham</author>
      <guid>https://priyatham.in/en/post/deploy-websites/</guid>
      <description>Code, as-it-is takes a lot of time to write, but also to host, build and deploy. I use a different set of tools for my usage. Most of them the conventional ones are free, they came with a catch. It always needs permission to your code, it could be used to train AI or would be limited to certain domains, certain number of runs or available for a limited trial period.
</description><content:encoded>&lt;p&gt;Code, as-it-is takes a lot of time to write, but also to host, build and deploy. I use a different set of tools for my usage. Most of them the conventional ones are free, they came with a catch. It always needs permission to your code, it could be used to train AI or would be limited to certain domains, certain number of runs or available for a limited trial period.&lt;/p&gt;

&lt;figure &gt;
			&lt;input id=&#34;fig-4abeeb16265112c3a8670a7eb658c16b-0&#34; class=&#34;marginpar-ctrl&#34; type=&#34;checkbox&#34; aria-controls=&#34;the-fig-4abeeb16265112c3a8670a7eb658c16b-0&#34; hidden&gt;&lt;/input&gt;
    &lt;label for=&#34;fig-4abeeb16265112c3a8670a7eb658c16b-0&#34;&gt;&lt;/label&gt;
        &lt;span id=&#34;the-fig-4abeeb16265112c3a8670a7eb658c16b-0&#34; class=&#34;marginpar abs&#34;&gt;
    
    A small section of my homepage of services
    
    &lt;/span&gt;
    

&lt;img src=&#34;https://priyatham.in/images/homepage-code-dep.png&#34;
  aria-describedby=&#34;fig-4abeeb16265112c3a8670a7eb658c16b-0&#34;
  loading=&#34;lazy&#34; /&gt;
    &lt;/figure&gt;

&lt;p&gt;I don&#39;t like what has become of GitHub, with unnecessary settings and bloat, it lost its simplicity. Gitea was a good option, but Forgejo was even better (I will not get into their fued) but any will work flawlessly. I wanted to host the code I wrote, instead of keeping it somewhere else. Coolify was a really cool and wonderful software that has almost everything I needed to deploy web applications.&lt;/p&gt;
&lt;h2 id=&#34;port-forward-for-forgejo-ssh&#34;&gt;Port Forward for Forgejo SSH&lt;/h2&gt;
&lt;p&gt;I can&#39;t rely on HTTPS for cloning and handling the git repos. I need a ssh way of doing things. But 22 is already for my own server from my public IP. So, a new port is in order to handle all of the git requests.&lt;/p&gt;
&lt;p&gt;My SDN needs to be able to forward all of them from the local network to the SDN through iptables. I wasn&#39;t really sure how to do but, I tried it. It worked flawlessly. Once I got it working, I was able to do it for DNS and FTP and many others which was awesome.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# forgejo ssh port: 2222
post-up iptables -t nat -A PREROUTING -i vmbr0 -p tcp --dport 2222 -j DNAT --to-destination 10.10.10.116:2222
post-down iptables -t nat -D PREROUTING -i vmbr0 -p tcp --dport 2222 -j DNAT --to-destination 10.10.10.116:2222

post-up iptables -t nat -A POSTROUTING -o vnt1 -p tcp --dport 2222 -d 10.10.10.116 -j MASQUERADE
post-down iptables -t nat -D POSTROUTING -o vnt1 -p tcp --dport 2222 -d 10.10.10.116 -j MASQUERADE

post-up iptables -A FORWARD -p tcp -d 10.10.10.116 --dport 2222 -j ACCEPT
post-down iptables -D FORWARD -p tcp -d 10.10.10.116 --dport 2222 -j ACCEPT
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;First section of post-up rules to forward incoming SSH traffic to the LXC container 116 on IP 10.10.10.116. The second one, post-down for outgoing with local networks in other interfaces and the last set of forward rules for external connection to be forward to the container.&lt;/p&gt;
&lt;p&gt;Once that was done, I wanted to be able to deploy it where I wanted, I could build it and server using nginx, but that would be a hassle for every single typo and commit I saw myself making and correcting. Running them in different ports, giving subdomains. Which I had something like Vercel or heruko when I used as an undergrad, something similar that I could self-host. After a good look, I found Coolify to be a good way to build and deploy prototypes.&lt;/p&gt;
&lt;p&gt;
&lt;figure &gt;
			&lt;input id=&#34;fig-4abeeb16265112c3a8670a7eb658c16b-1&#34; class=&#34;marginpar-ctrl&#34; type=&#34;checkbox&#34; aria-controls=&#34;the-fig-4abeeb16265112c3a8670a7eb658c16b-1&#34; hidden&gt;&lt;/input&gt;
    &lt;label for=&#34;fig-4abeeb16265112c3a8670a7eb658c16b-1&#34;&gt;&lt;/label&gt;
        &lt;span id=&#34;the-fig-4abeeb16265112c3a8670a7eb658c16b-1&#34; class=&#34;marginpar abs&#34;&gt;
    
    The Forgejo server config has variables that can check standard ssh port to something like 2222
    
    &lt;/span&gt;
    

&lt;img src=&#34;https://priyatham.in/images/forgejo-ssh-server-config.png&#34;
  aria-describedby=&#34;fig-4abeeb16265112c3a8670a7eb658c16b-1&#34;
  loading=&#34;lazy&#34; /&gt;
    &lt;/figure&gt;


&lt;figure &gt;
			&lt;input id=&#34;fig-4abeeb16265112c3a8670a7eb658c16b-2&#34; class=&#34;marginpar-ctrl&#34; type=&#34;checkbox&#34; aria-controls=&#34;the-fig-4abeeb16265112c3a8670a7eb658c16b-2&#34; hidden&gt;&lt;/input&gt;
    &lt;label for=&#34;fig-4abeeb16265112c3a8670a7eb658c16b-2&#34;&gt;&lt;/label&gt;
        &lt;span id=&#34;the-fig-4abeeb16265112c3a8670a7eb658c16b-2&#34; class=&#34;marginpar abs&#34;&gt;
    
    How the unconventional port number is shown for cloning my git repo
    
    &lt;/span&gt;
    

&lt;img src=&#34;https://priyatham.in/images/forgejo-ssh-repo.png&#34;
  aria-describedby=&#34;fig-4abeeb16265112c3a8670a7eb658c16b-2&#34;
  loading=&#34;lazy&#34; /&gt;
    &lt;/figure&gt;
&lt;/p&gt;
&lt;h2 id=&#34;subdomains-for-coolify&#34;&gt;Subdomains for Coolify&lt;/h2&gt;
&lt;p&gt;Thinking and designing the whole system. The straight forward approach was to have subdomains like *.priyatham.in. But wait, I have many other services (I think close to 25, &lt;a href=&#34;https://home.priyatham.in&#34; target=&#34;_blank&#34; rel=&#34;external noopener noreferrer nofollow&#34;&gt;All of them&lt;/a&gt;). Conflicts can occur. I didn&#39;t want to deal with them or think about it. So a multi-level subdomain ( I call it sub subdomain) could be the solution. *.deploy.priyatham.in would work giving it a way for me to differentiate between my regular services and test sites.&lt;/p&gt;
&lt;p&gt;What about the UI of Coolify ? That can&#39;t be inside. So I reverse proxied it with deploy-ui.priyatham.in.&lt;/p&gt;
&lt;p&gt;I couldn&#39;t get the name of the repo to be the sub subdomain automatically once I create the project in the UI. I have to manually go and edit it as I deploy it out.&lt;/p&gt;
&lt;h3 id=&#34;certbot-for-sub-subdomain&#34;&gt;Certbot for sub-subdomain&lt;/h3&gt;
&lt;p&gt;I had the Certbot plugins to do the renewels and creation of certificates for regular subdomains, this one needs a new one. Since I wanted a wildcard domain with deploy it should *.deploy.priyatham.in hence have to create the certs for the same. I use the porkbun plugin because that&#39;s where I have my nameservers and the domain management. But the command is (for me to copy paste later on):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;~# certbot certonly \                                
--dns-porkbun-credentials .../credentials.ini \
-d &amp;quot;*.deploy.priyatham.in&amp;quot; \
-d priyatham.in
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;deploy-keys-with-forgejo-and-coolify&#34;&gt;Deploy keys with Forgejo and Coolify&lt;/h2&gt;
&lt;p&gt;Deploy keys are used for exactly what they say they are. To deploy private git repos with ssh safely and properly.&lt;/p&gt;
&lt;p&gt;Coolify has a weird of doing it (or I don&#39;t know the right way), there&#39;s a back and forth of doing it,&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create the Deploy keys&lt;/li&gt;
&lt;li&gt;add it to authorized keys&lt;/li&gt;
&lt;li&gt;add it to your Forgejo repo&lt;/li&gt;
&lt;li&gt;create the project and add the git repo selecting the same deploy key.&lt;/li&gt;
&lt;/ol&gt;

&lt;figure &gt;
			&lt;input id=&#34;fig-4abeeb16265112c3a8670a7eb658c16b-3&#34; class=&#34;marginpar-ctrl&#34; type=&#34;checkbox&#34; aria-controls=&#34;the-fig-4abeeb16265112c3a8670a7eb658c16b-3&#34; hidden&gt;&lt;/input&gt;
    &lt;label for=&#34;fig-4abeeb16265112c3a8670a7eb658c16b-3&#34;&gt;&lt;/label&gt;
        &lt;span id=&#34;the-fig-4abeeb16265112c3a8670a7eb658c16b-3&#34; class=&#34;marginpar abs&#34;&gt;
    
    Dialog box to create one, the action required in bold is what I missed for hours.
    
    &lt;/span&gt;
    

&lt;img src=&#34;https://priyatham.in/images/deploy-key-coolify.png&#34;
  aria-describedby=&#34;fig-4abeeb16265112c3a8670a7eb658c16b-3&#34;
  loading=&#34;lazy&#34; /&gt;
    &lt;/figure&gt;


&lt;figure &gt;
			&lt;input id=&#34;fig-4abeeb16265112c3a8670a7eb658c16b-4&#34; class=&#34;marginpar-ctrl&#34; type=&#34;checkbox&#34; aria-controls=&#34;the-fig-4abeeb16265112c3a8670a7eb658c16b-4&#34; hidden&gt;&lt;/input&gt;
    &lt;label for=&#34;fig-4abeeb16265112c3a8670a7eb658c16b-4&#34;&gt;&lt;/label&gt;
        &lt;span id=&#34;the-fig-4abeeb16265112c3a8670a7eb658c16b-4&#34; class=&#34;marginpar abs&#34;&gt;
    
    The place where to add the created deploy key of Forgejo side
    
    &lt;/span&gt;
    

&lt;img src=&#34;https://priyatham.in/images/forgejo-deploy-key.png&#34;
  aria-describedby=&#34;fig-4abeeb16265112c3a8670a7eb658c16b-4&#34;
  loading=&#34;lazy&#34; /&gt;
    &lt;/figure&gt;

&lt;p&gt;I wasted a lot of time by forgetting to add authorized_keys to the server that runs my deployed application. It never gave me a clear warning after creating it, so it disabled the keys with no response.&lt;/p&gt;
&lt;h2 id=&#34;auto-builds-and-webhooks&#34;&gt;Auto builds and Webhooks&lt;/h2&gt;
&lt;p&gt;Wouldn&#39;t be cool if I don&#39;t have to manually deploy every change ? Webhooks are just for that. They follow similar steps. Creating the webhook with a secret. Adding it into Forgejo webhook, there&#39;s no clear webhook integration for coolify so I just used the forgejo one, with the targer url, secret and branch filters.&lt;/p&gt;
&lt;p&gt;So let&#39;s say I only want to trigger when a commit is done to the main branch and not any other ones, I can create the filter to only include main instead of &#39;*&#39;.&lt;/p&gt;

&lt;figure &gt;
			&lt;input id=&#34;fig-4abeeb16265112c3a8670a7eb658c16b-5&#34; class=&#34;marginpar-ctrl&#34; type=&#34;checkbox&#34; aria-controls=&#34;the-fig-4abeeb16265112c3a8670a7eb658c16b-5&#34; hidden&gt;&lt;/input&gt;
    &lt;label for=&#34;fig-4abeeb16265112c3a8670a7eb658c16b-5&#34;&gt;&lt;/label&gt;
        &lt;span id=&#34;the-fig-4abeeb16265112c3a8670a7eb658c16b-5&#34; class=&#34;marginpar abs&#34;&gt;
    
    Gitea webhook works with Forgejo, for now.
    
    &lt;/span&gt;
    

&lt;img src=&#34;https://priyatham.in/images/coolify-webhook.png&#34;
  aria-describedby=&#34;fig-4abeeb16265112c3a8670a7eb658c16b-5&#34;
  loading=&#34;lazy&#34; /&gt;
    &lt;/figure&gt;


&lt;figure &gt;
			&lt;input id=&#34;fig-4abeeb16265112c3a8670a7eb658c16b-6&#34; class=&#34;marginpar-ctrl&#34; type=&#34;checkbox&#34; aria-controls=&#34;the-fig-4abeeb16265112c3a8670a7eb658c16b-6&#34; hidden&gt;&lt;/input&gt;
    &lt;label for=&#34;fig-4abeeb16265112c3a8670a7eb658c16b-6&#34;&gt;&lt;/label&gt;
        &lt;span id=&#34;the-fig-4abeeb16265112c3a8670a7eb658c16b-6&#34; class=&#34;marginpar abs&#34;&gt;
    
    Add webhook integration with forgejo, the events and branch filters are the key.
    
    &lt;/span&gt;
    

&lt;img src=&#34;https://priyatham.in/images/forgejo-webhook.png&#34;
  aria-describedby=&#34;fig-4abeeb16265112c3a8670a7eb658c16b-6&#34;
  loading=&#34;lazy&#34; /&gt;
    &lt;/figure&gt;

&lt;h2 id=&#34;future&#34;&gt;Future&lt;/h2&gt;
&lt;p&gt;Forgejo runner is what I am looking at currently, trying to include that, but with all the other things I have to do (The never ending OIDC connections, or the 5 pending articles) I decided to try it out later.&lt;/p&gt;
</content:encoded>
      <enclosure url="/images/code-deployment-cover-1.png" length="0" type="image/jpeg" />
    </item>
  </channel>
</rss>
