<?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>Forem: Nixopus</title>
    <description>The latest articles on Forem by Nixopus (@nixopus).</description>
    <link>https://forem.com/nixopus</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%2Forganization%2Fprofile_image%2F11732%2F077d9019-9f24-4ce0-b028-d1847c6b8273.png</url>
      <title>Forem: Nixopus</title>
      <link>https://forem.com/nixopus</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/nixopus"/>
    <language>en</language>
    <item>
      <title>Inside Nixopus: How We Manage Our Database Migrations?</title>
      <dc:creator>Shravan Kumar B</dc:creator>
      <pubDate>Fri, 27 Jun 2025 13:44:31 +0000</pubDate>
      <link>https://forem.com/nixopus/inside-nixopus-how-we-manage-our-database-migrations-3i34</link>
      <guid>https://forem.com/nixopus/inside-nixopus-how-we-manage-our-database-migrations-3i34</guid>
      <description>&lt;p&gt;This article mainly focuses on laying out our foundational approach to setting up the &lt;a href="https://github.com/raghavyuva/nixopus/" rel="noopener noreferrer"&gt;database migration system for Nixopus&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Database migrations&lt;/em&gt;&lt;/strong&gt; are often the unsung heroes of software application development. They work silently in the background, ensuring that your database schema evolves safely alongside your application code. Yet for many teams, this is a major source of stress and uncertainty. In this blog, we will explore how we have set up the migration framework for Nixopus. This has become a pivotal step in our developmental and self-host workflow.&lt;/p&gt;

&lt;p&gt;To start with, let us first explore and understand what we mean by &lt;strong&gt;&lt;em&gt;database migration&lt;/em&gt;&lt;/strong&gt;. As we always do, let us take an analogy.&lt;/p&gt;

&lt;p&gt;We often use different database systems like MySQL, PostgreSQL, MongoDB, etc, for data persistence. These data are stored in the form of Tables having columns and rows.&lt;/p&gt;

&lt;p&gt;As the application grows, the number of tables grows, and the data defined at each table might vary and change; hence, it is very important to keep track of these changes.&lt;/p&gt;

&lt;p&gt;Tables are at the database system level, whereas at the programmatic level, we maintain them with something called &lt;strong&gt;&lt;em&gt;schemas&lt;/em&gt;&lt;/strong&gt;. Like a house blueprint that dictates where rooms, doors, and wiring go, a schema simply defines how the data is organized and connected.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhumm2q3dkpxw5zv5180m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhumm2q3dkpxw5zv5180m.png" alt="schema-vs-tables"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, let's imagine that you decide to change the blueprint mid-build, to add a new room or window, you need to carefully make changes to the existing blueprint such that you don’t end up collapsing the walls down.&lt;/p&gt;

&lt;p&gt;This problem is addressed at the schema level to ensure the changes in the existing tables, which may be in the form of adding new columns, altering the type of existing columns, or adding new tables, are handled through what we call &lt;strong&gt;&lt;em&gt;Database Migrations&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx9pm6demw0q72mcmykqc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx9pm6demw0q72mcmykqc.png" alt="data-migration-meme"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When we started building Nixopus, we quickly realized that database schema management would be critical to our success in self-hosting and local development setups. We planned with an expectation set that eventually we would see multiple developers working on different features, frequent deployments, and the need to support both development and production environments, which would require a very streamlined process to handle database migration.&lt;/p&gt;

&lt;p&gt;We had aligned on the following factors that our migration system would have to adhere to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Reliability&lt;/em&gt;&lt;/strong&gt;: Migrations must execute consistently across all envs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automatic&lt;/strong&gt;: No manual intervention should be required during deployments&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Forward &amp;amp; Backward Compatible&lt;/strong&gt;: Ensure easy rollback scenarios&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Separations of Concerns&lt;/strong&gt;: Organization of migrations by domain or feature&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Many existing tools either lacked the flexibility we needed or came with unnecessary complexity, be it in terms of testability or adding rollbacks in case of errors, etc.&lt;/p&gt;

&lt;p&gt;Hence, we decided to build our migration system tailored to our needs and requirements using a tool called &lt;a href="https://bun.uptrace.dev/guide/migrations.html" rel="noopener noreferrer"&gt;Bun ORM&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ficreopncr72qkqyyq2se.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ficreopncr72qkqyyq2se.png" alt="sql-vs-orm"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To those who are not aware of the terminology ORM, let me give a glimpse of it; ORM, otherwise called as &lt;strong&gt;&lt;em&gt;Object Relational Mapper&lt;/em&gt;&lt;/strong&gt;, is like a waiter at a restaurant, to who you tell what you want, he/she goes to kitchen(I mean database), then brings back your order(data) as perfectly plated objects in ready to use form.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F605ksjoeg5exjzcot4vv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F605ksjoeg5exjzcot4vv.png" alt="who-orm-who-orm-bun-orm"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Without ORM, you would have been presented with raw vegetables and ingredients straight from the kitchen (of course, by that I mean the database), and you would have to do all the cooking yourself, which means writing and managing every query and data transformation.&lt;/p&gt;

&lt;p&gt;Coming back, we have built our migration system around a simple yet &lt;strong&gt;powerful concept&lt;/strong&gt;, where a pair of SQL files represents every database change:&lt;/p&gt;

&lt;p&gt;1) &lt;strong&gt;Applying the change (up migrations)&lt;/strong&gt;&lt;br&gt;
2) &lt;strong&gt;Rolling it back (down migrations)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnu808jb4jnzs8vl5c5ko.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnu808jb4jnzs8vl5c5ko.png" alt="migration-code-structure-flow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This approach has helped our system to easily take care of schema evolution and database versioning.&lt;/p&gt;

&lt;p&gt;The migration system follows a defined life cycle:&lt;/p&gt;

&lt;p&gt;1) &lt;strong&gt;Discovery&lt;/strong&gt;: The system scans the &lt;code&gt;api/migrations&lt;/code&gt; directory&lt;/p&gt;

&lt;p&gt;2) &lt;strong&gt;Parsing&lt;/strong&gt;: Migration files are parsed and paired (up/down migrations)&lt;/p&gt;

&lt;p&gt;3) &lt;strong&gt;Ordering&lt;/strong&gt;: Migrations are sorted by their numeric IDs&lt;/p&gt;

&lt;p&gt;4) &lt;strong&gt;State Check&lt;/strong&gt;: The system compares file system migrations with applied migrations in the database&lt;/p&gt;

&lt;p&gt;5) &lt;strong&gt;Execution&lt;/strong&gt;: Pending migrations are executed in transactions&lt;/p&gt;

&lt;p&gt;6) &lt;strong&gt;Recordings&lt;/strong&gt;: Successfully applied migrations are recorded in the migration table&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fej1w31t3m718xo63qfyo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fej1w31t3m718xo63qfyo.png" alt="migration-system-lifecycle"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that you know an overview of our setup and how it works, you might wonder what actually sets our approach apart? Fair enough!!!!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwnoxp32ng9v8t7ajwhip.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwnoxp32ng9v8t7ajwhip.png" alt="migration-differentiator"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;1) &lt;strong&gt;&lt;em&gt;Domain Driven Structure&lt;/em&gt;&lt;/strong&gt;: Instead of throwing all migrations into a single directory, we have organized them by domain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;api/migrations/
├── applications/   # App deployment features
├── audit/          # Audit logging and compliance
├── auth/           # Authentication &amp;amp; authorization
├── containers/     # Container management
├── domains/        # Domain and DNS management
├── feature-flags/  # Feature toggle system
├── integrations/   # Third-party integrations
├── notifications/  # Notification system
├── organizations/  # Multi-tenancy &amp;amp; organizations
├── rbac/           # Role-based access control
└── users/          # User management and profiles
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This structure makes it easy for us to find and create migrations related to specific work or flow, helping us avoid confusion or conflicts.&lt;/p&gt;

&lt;p&gt;2) &lt;strong&gt;Automatic migration execution on application startup&lt;/strong&gt;: One of the key design decisions was to make migrations completely automatic. When the application starts, the migration system runs before any other initialization. This approach eliminated the need for separate deployment and ensures that the database schema is always up to date when the application starts.&lt;/p&gt;

&lt;p&gt;3) &lt;strong&gt;Atomic, Transactional Migrations&lt;/strong&gt;: Every migration runs inside a database transaction, ensuring atomicity. If any part of a migration fails, the entire migration is rolled back, ensuring that the schema remains fully consistent.&lt;/p&gt;

&lt;p&gt;4) &lt;strong&gt;&lt;em&gt;Bidirectional Migrations&lt;/em&gt;&lt;/strong&gt;: Every migrations have 2 files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;seqno_entity_up.sql&lt;/code&gt; (applies the change)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;seqno_entity_down.sql&lt;/code&gt; (rolls back the change)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This ensures that we can always roll back changes if something goes wrong.&lt;/p&gt;

&lt;p&gt;As we are close to concluding the deep dive into the first of many articles of the &lt;strong&gt;&lt;em&gt;Inside Nixopus&lt;/em&gt;&lt;/strong&gt; series, I would like to highlight some of the major learnings and key takeaways:&lt;/p&gt;

&lt;p&gt;1) &lt;strong&gt;Keep each migration small and focused&lt;/strong&gt;for easier review or rollback.&lt;br&gt;
2) Ensure to keep a &lt;em&gt;&lt;strong&gt;down migration&lt;/strong&gt; for every &lt;strong&gt;up migration&lt;/strong&gt;&lt;/em&gt;, ensuring roll backs are easy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcz9ijjmrruycdzpx65cn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcz9ijjmrruycdzpx65cn.png" alt="key-learning-takeaways-nixopus"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The key insight is that sometimes the best tool is the one you build yourself. By understanding our specific needs and constraints, we were able to set up our migration system that fits perfectly into our development workflow and easy self-hosting.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F66k8t8vncrm2g0vzpkym.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F66k8t8vncrm2g0vzpkym.png" alt="nixopus"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The project, as we publish this article, is in the Alpha stage. &lt;/p&gt;

&lt;p&gt;You can check it out on &lt;a href="https://github.com/raghavyuva/nixopus" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; and see for yourself.&lt;/p&gt;

&lt;p&gt;To sum it up, the approach helped us change schema changes from a headache to a reliable process.&lt;/p&gt;

&lt;p&gt;If you would like to get involved or have questions, join our Discord community for real-time support and feedback. You can self-host Nixopus today, subscribe for updates, and stay tuned as we roll out new features and stability enhancements.&lt;/p&gt;

&lt;p&gt;
        &lt;a href="https://discord.gg/skdcq39Wpv" rel="noopener noreferrer"&gt;
          &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F31022056%2F158916278-4504b838-7ecb-4ab9-a900-7dc002aade78.png" alt="Join our Discord Community" width="200"&gt;
        &lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;We have recently collaborated with &lt;strong&gt;&lt;em&gt;HostUp&lt;/em&gt;&lt;/strong&gt;, a reliable VPS provider based in Sweden, to bring you an exclusive deal of &lt;strong&gt;&lt;em&gt;10% off&lt;/em&gt;&lt;/strong&gt; recurring on any VPS plan. Whether you choose to self-host Nixopus or deploy containerized apps, this is the perfect opportunity to secure rock-solid infrastructure at a &lt;a href="https://discord.com/invite/skdcq39Wpv" rel="noopener noreferrer"&gt;Discord Community&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://hostup.se/en/vps/" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fitnnybtsdrgzmv5dj0lz.png" alt="partnership"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Stay tuned for more freshly brewed content.&lt;/p&gt;

&lt;p&gt;That's all for now. Thank you for reading.&lt;/p&gt;

&lt;p&gt;Signing off until next time.&lt;/p&gt;

&lt;p&gt;Thank you.&lt;/p&gt;




&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/nixopus" rel="noopener noreferrer"&gt;
        nixopus
      &lt;/a&gt; / &lt;a href="https://github.com/nixopus/nixopus" rel="noopener noreferrer"&gt;
        nixopus
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Open Source Alternative to vercel, heroku, netlify with simplified workflows
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div&gt;
&lt;a href="https://nixopus.com" rel="nofollow noopener noreferrer"&gt;&lt;img width="1800" height="520" alt="Heading(4)" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fprivate-user-images.githubusercontent.com%2F53376933%2F489183579-e103a9df-7abf-4f78-b75a-221331231247.png%3Fjwt%3DeyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NzQ2NDk5ODEsIm5iZiI6MTc3NDY0OTY4MSwicGF0aCI6Ii81MzM3NjkzMy80ODkxODM1NzktZTEwM2E5ZGYtN2FiZi00Zjc4LWI3NWEtMjIxMzMxMjMxMjQ3LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNjAzMjclMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjYwMzI3VDIyMTQ0MVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTZhNWNjZDk4ZWUzMjg1Mjg0N2E3NDE1N2JlZWM5YWRiODBjMDFlZWJjZjhjMTk3Mzg1NjEzODAwNWNjMTgxZDQmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.wllWcFyhKI6-epgomUARL0MegOdLw4DOJfrpa-34GIQ"&gt;&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;
 Open Source alternative to vercel, heroku, netlify with Terminal integration, and Self Hosting capabilities
&lt;/p&gt;

&lt;p&gt;
  &lt;a href="https://nixopus.com" rel="nofollow noopener noreferrer"&gt;&lt;b&gt;Website&lt;/b&gt;&lt;/a&gt; •
  &lt;a href="https://docs.nixopus.com" rel="nofollow noopener noreferrer"&gt;&lt;b&gt;Documentation&lt;/b&gt;&lt;/a&gt; •
  &lt;a href="https://nixopus.com/blog" rel="nofollow noopener noreferrer"&gt;&lt;b&gt;Blog&lt;/b&gt;&lt;/a&gt; •
  &lt;a href="https://discord.gg/skdcq39Wpv" rel="nofollow noopener noreferrer"&gt;&lt;b&gt;Discord&lt;/b&gt;&lt;/a&gt; •
  &lt;a href="https://github.com/nixopus/nixopus/discussions/262" rel="noopener noreferrer"&gt;&lt;b&gt;Roadmap&lt;/b&gt;&lt;/a&gt;
&lt;/p&gt;



&lt;p&gt;
 &lt;a href="https://trendshift.io/repositories/15336" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/b1e517a10005ef87f5f3e79c6bff19c1231008ede15755cf0ae5b59cc68544ec/68747470733a2f2f7472656e6473686966742e696f2f6170692f62616467652f7265706f7369746f726965732f3135333336" alt="nixopus/nixopus | Trendshift" width="250" height="55"&gt;&lt;/a&gt;
&lt;/p&gt;



&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/nixopus/nixopus/assets/nixopus_dashboard.jpeg"&gt;&lt;img width="1210" height="764" alt="image" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fnixopus%2Fnixopus%2Fassets%2Fnixopus_dashboard.jpeg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Important Note&lt;/strong&gt;: Nixopus is currently in alpha/pre-release stage and is not yet ready for production use. While you're welcome to try it out, we recommend waiting for the beta or stable release before using it in production environments. The platform is still undergoing testing and development.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Features&lt;/h1&gt;
&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Deploy apps with one click.&lt;/strong&gt; No config files, no SSH commands.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Manage files in your browser.&lt;/strong&gt; Drag, drop, edit. Like any file manager.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Built-in terminal.&lt;/strong&gt; Access your server without leaving the page.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-time monitoring.&lt;/strong&gt; See CPU, RAM, disk usage at a glance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auto SSL certificates.&lt;/strong&gt; Your domains get HTTPS automatically.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub integration.&lt;/strong&gt; Push code → auto deploy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Proxy management.&lt;/strong&gt; Route traffic with Caddy reverse proxy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Smart alerts.&lt;/strong&gt; Get notified via Slack, Discord, or email when something's wrong.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Installation&lt;/h2&gt;…&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/nixopus/nixopus" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



</description>
      <category>go</category>
      <category>opensource</category>
      <category>database</category>
      <category>postgres</category>
    </item>
    <item>
      <title>Nixopus: Simplifying VPS Management</title>
      <dc:creator>Shravan Kumar B</dc:creator>
      <pubDate>Mon, 23 Jun 2025 18:03:39 +0000</pubDate>
      <link>https://forem.com/nixopus/nixopus-simplifying-vps-management-4g0f</link>
      <guid>https://forem.com/nixopus/nixopus-simplifying-vps-management-4g0f</guid>
      <description>&lt;p&gt;This article is my reflection on the journey of how I relied on free tier clouds and platform specific hosting until I discovered VPS. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9h9rvhdq7040pvgrt9mk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9h9rvhdq7040pvgrt9mk.png" alt="my journey from using cloud setup to VPS" width="800" height="547"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Shipping Code while Sipping Coffee&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Back then, I was still trying to figure out and understand how all this worked. Starting from which command did what, which service refused to start, and why things that worked on my local; didn’t work when deployed (Thank God for Docker)&lt;/p&gt;

&lt;p&gt;I still recall one of my earliest deployment. It was &lt;a href="https://github.com/shravan20/github-readme-quotes" rel="noopener noreferrer"&gt;github-readme-quotes&lt;/a&gt; app on Heroku. A simple git push to deploy felt magical. I didn’t really have to care how it worked. I just knew that if I followed the documentation devoutly, it was assured to work; if not, StackOverflow always had my back.&lt;/p&gt;

&lt;p&gt;This was the same with Firebase, Render, or Netlify for static stuff. All of them taught me how to ship quickly. &lt;/p&gt;

&lt;p&gt;But then came the real world; need to host private apps, things that need ports, memory tuning, background workers, cron jobs, etc. Soon, those magical platforms started speaking back and complaining to me:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;"You can’t bind that port"&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;"You’re out of free dynos"&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;"Exceed dynos quota for the month"&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I found myself stuck on an architectural impasse till the day when one of the engineers I know suggested saying these lines, “Just spin up a VPS“. That advice removed the roadblock.&lt;/p&gt;

&lt;p&gt;To those who are not aware of what is &lt;strong&gt;&lt;em&gt;VPS&lt;/em&gt;&lt;/strong&gt;? How is it different from Server? Let me try to explain it with an analogy:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Imagine you’ve built a website and now you want to make it public, so you need to host it. Basically put it out on a computer that is always online. This is called hosting.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2j7ke33delch7jw8wo9x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2j7ke33delch7jw8wo9x.png" alt="How to Hosting your site" width="800" height="514"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before hosting a website, there are 3 types of hosting, each of which balances cost, control, and performance in its own way. Let us take an analogy of hosting with where we live:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;Shared Hosting&lt;/em&gt;&lt;/strong&gt; is like renting a room in PG, which is extremely affordable, but you share your resources with others and have very little control&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;Virtual Private Server&lt;/em&gt;&lt;/strong&gt; (aka VPS) is like having your own apartment, you get private space, you are secure, decorate and customize as you want, and truly call your own.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;Dedicated Server&lt;/em&gt;&lt;/strong&gt; is like leasing an entire bungalow; you alone enjoy all its resources and full autonomy at a very high price.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F78id0zjgbqfldv4sejxw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F78id0zjgbqfldv4sejxw.png" alt="understanding VPS" width="800" height="784"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dedicated Servers&lt;/strong&gt; are either some crazy big computers in freezing cold data centers or virtual computers carved out of bigger machines using virtualization.&lt;/p&gt;

&lt;p&gt;So, yep, VPS was that sweet middle ground; cost of a simple 1 BHK flat with freedom to knock down a wall (just kidding). So that balance I needed came in the form of VPS.&lt;/p&gt;

&lt;p&gt;So I picked a VPS provider, bought a VPS server for 7€ (~₹697). I got an IP address, username(root), and SSH details. &lt;/p&gt;

&lt;p&gt;Till then, I had learnt what VPS was and lil about behind the scenes from the few Google searches  I had done. I understood that a VPS is a virtual machine running on a larger physical server with its own dedicated RAM, disk space, and CPU. And fortunately, since I was already comfortable with Linux commands, so felt navigating this environment shouldn’t be a problem.&lt;/p&gt;

&lt;p&gt;Since I had previously tinkered quite a lot with Raspberry Pi, by hooking it to the local network and SSH’ing into it from my laptop, I already knew that the only way to connect to my VPS was using SSH.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3pc43sa7g5oxh8ghng7y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3pc43sa7g5oxh8ghng7y.png" alt=" " width="800" height="543"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To those who do not know what SSH means, let us again explore it with an analogy:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;SSH is like a passport to access your VPS&lt;/em&gt;&lt;/strong&gt;. With SSH, you can remotely step inside your VPS like teleporting into a distant terminal. It was like I’d opened the door to another computer without leaving mine. There is no UI, browser, but a simple terminal access for your VPS and raw power.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcd849rottalq04z538aw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcd849rottalq04z538aw.png" alt="just linux haha" width="559" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every server I touched so far ran Linux, so I already had a clear cut understanding. So for everything looked good.&lt;/p&gt;

&lt;p&gt;I started slowly moving my apps to the VPS, and running the scripts to have it run on the VPS. I ran into another hurdle; I was only able to access the deployed applications or services using their IP address, like &lt;code&gt;http://123.45.67.89&lt;/code&gt;. Unlike Heroku or Netlify, which provided me ready made subdomain for a project like [&lt;code&gt;github-readme-quotes.herokuapp.com&lt;/code&gt;], my move to a VPS setup left me staring at a bare IP address.&lt;/p&gt;

&lt;p&gt;I knew I needed a proper name and URL, &lt;code&gt;some-project.com&lt;/code&gt;, and that’s where DNS comes in. &lt;/p&gt;

&lt;p&gt;To those who do not know what &lt;strong&gt;DNS&lt;/strong&gt; is, consider it as a &lt;strong&gt;Internet’s Yellow Page (Phonebook)&lt;/strong&gt;; basically translates domain names to IP addresses. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh16osgkfsihc61kau7nj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh16osgkfsihc61kau7nj.png" alt="yellow-page" width="768" height="512"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A lot of them still find tying a domain to a VPS surprisingly tricky. Hence, I keep a simple recipe:&lt;/p&gt;

&lt;p&gt;1) You buy a domain from Domain Registrar&lt;br&gt;
2) Point it to your VPS IP using A records in your registrar’s control panel&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Type: A  
Host: @  
Value: 123.45.67.89
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3) Set up Nginx&lt;br&gt;
4) Configure SSL&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F39wnt05pkg4pq4veabaw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F39wnt05pkg4pq4veabaw.png" alt=" " width="800" height="835"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You might be wondering, what are these Nginx and SSL? Let us understand this better, diving a little deeper into the concepts.&lt;/p&gt;

&lt;p&gt;Every service on your server or computer communicates over a specific port; some of them are already predefined, say:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;SSH&lt;/code&gt; on port &lt;code&gt;22&lt;/code&gt; for remote access&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;HTTP&lt;/code&gt; on port &lt;code&gt;80&lt;/code&gt; for unencrypted web traffic&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;HTTPS&lt;/code&gt; on port &lt;code&gt;443&lt;/code&gt; for encrypter web traffic via SSL/TLS&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By now, you must have understood that SSL/TLS is what turns ordinary HTTP into secure HTTPS, making sure that the data between user and server stays private and secure.&lt;/p&gt;

&lt;p&gt;Nginx is the traffic police on my VPS which is mainly responsible for forwarding user requests to respective applications, handling SSL encryption, and serving the static contents.&lt;/p&gt;

&lt;p&gt;You must be wondering, &lt;strong&gt;&lt;em&gt;"Voila, Great, now that everything is in place, and the hard part is over, life must be easier"&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Hahaha!! Well, thats exactly when the real problems began. Over time, deployments process became a familiar and routine; rather painful routing I would say.&lt;/p&gt;

&lt;p&gt;This routing masked a lot of headaches: broken configs, panicky Nginx configuration tweaks, dread thought of “Did I actually run the right script?“ and manual responsibility of deploying all of these without any automations and verifying the releases.&lt;/p&gt;

&lt;p&gt;Eventually, I scripted it all, but I can never forget those initial days of manual, shaky deployments. They taught me the cost of carelessness, where I had spent a day to find one config misplaced. It wasn’t about skill, but rather about mental tax caused due to this.&lt;/p&gt;

&lt;p&gt;By then, I had realised managing multiple applications on a single VPS only made things worse, where I had to juggle and handle process monitoring, checking the logs, and mainly running update scripts.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdj6vony210gqg82f3sey.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdj6vony210gqg82f3sey.png" alt="VPS monitoring" width="578" height="482"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;With power comes great responsibility&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm7hqma5tahj5zzo2eigy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm7hqma5tahj5zzo2eigy.png" alt="on a lighter note" width="600" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With experience comes great clarity; I started seeing patterns in the process I followed. I’ve been doing this for a while now, everytime I spun up a VPS or deploy new project on a VPS, I found myself re-Googling the same 20 commands. I observed that across some major pain points:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Copy-pasting Identical configurations&lt;/li&gt;
&lt;li&gt;Deployment failures&lt;/li&gt;
&lt;li&gt;DNS setups&lt;/li&gt;
&lt;li&gt;Setting up Firewall rules&lt;/li&gt;
&lt;li&gt;Forgetting about SSL renewals&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It was the same story day in and day out. That is when I asked myself, is this problem not actually solved and standardized yet? Do we not have a tool that streamlines and simplifies the VPS management?&lt;/p&gt;

&lt;p&gt;My search led me to Nixopus, an indie tool built by a community led by Raghav to tackle these exact frustrations. As we talked, it became clear that Nixopus wasn’t born from ambition rather from fatigue, the kind that drives you to refactor your life. It promised everything I had been hunting for.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fois17ln8re3q31a9gekb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fois17ln8re3q31a9gekb.png" alt="VPS Management SOlution" width="800" height="229"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Though in Alpha stage, I’ve started using it for managing my VPS and even actively contributing to improvements whenever I can. I am convinced that this project has a bright future. You check it out on &lt;a href="https://github.com/raghavyuva/nixopus" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; and see for yourself.&lt;/p&gt;

&lt;p&gt;If you would like to get involved or have questions, join our Discord community for real-time support and feedback. You can self-host Nixopus today, subscribe for updates, and stay tuned as we roll out new features and stability enhancements.&lt;/p&gt;

&lt;p&gt;We have recently collaborated with HostUp, a reliable VPS provider based in Sweden, to bring you an exclusive deal of 10% off recurring on any VPS plan. Whether you choose to self-host Nixopus or deploy containerized apps, this is the perfect opportunity to secure rock-solid infrastructure at a &lt;a href="https://discord.com/invite/skdcq39Wpv" rel="noopener noreferrer"&gt;Discord Community&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://hostup.se/en/vps/" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fitnnybtsdrgzmv5dj0lz.png" alt="partnership" width="800" height="236"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can claim your VPS coupon and start building with Nixopus today.&lt;/p&gt;

&lt;p&gt;Join our &lt;a href="https://discord.com/invite/skdcq39Wpv" rel="noopener noreferrer"&gt;Discord&lt;/a&gt; community, you’re always welcome to hop in for community support!&lt;/p&gt;

&lt;p&gt;Summing it up, my journey from building on free-tier clouds and shared hosting to fully embracing VPS has taught me one thing is that having control doesn't have to mean endless repetitive manual work and management. Nixopus bridges that gap, so that from now on you can focus on what really matters.&lt;/p&gt;

&lt;p&gt;Stay tuned for more freshly brewed content. &lt;/p&gt;

&lt;p&gt;That’s all for now. Thank you for reading.&lt;/p&gt;

&lt;p&gt;Signing off until next time.&lt;/p&gt;

&lt;p&gt;Happy Learning!!&lt;/p&gt;

</description>
      <category>devops</category>
      <category>beginners</category>
      <category>selfhosting</category>
      <category>cloud</category>
    </item>
  </channel>
</rss>
