<?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: Chibuike Okoye</title>
    <description>The latest articles on DEV Community by Chibuike Okoye (@christophchi).</description>
    <link>https://dev.to/christophchi</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%2F3970137%2Fbf570c55-1a40-4471-b807-582f51d680dd.png</url>
      <title>DEV Community: Chibuike Okoye</title>
      <link>https://dev.to/christophchi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/christophchi"/>
    <language>en</language>
    <item>
      <title>How to Back Up Your Server Files and Database (Before You Learn the Hard Way)</title>
      <dc:creator>Chibuike Okoye</dc:creator>
      <pubDate>Fri, 05 Jun 2026 20:34:21 +0000</pubDate>
      <link>https://dev.to/christophchi/how-to-back-up-your-server-files-and-database-before-you-learn-the-hard-way-2962</link>
      <guid>https://dev.to/christophchi/how-to-back-up-your-server-files-and-database-before-you-learn-the-hard-way-2962</guid>
      <description>&lt;p&gt;There is a special kind of silence that hits you the moment you realize your data is gone. No database. No uploads. No &lt;code&gt;.env&lt;/code&gt;. Just an empty folder where two years of work used to live.&lt;/p&gt;

&lt;p&gt;I have felt it. Most developers feel it exactly once, because once is enough to make you religious about backups for the rest of your life.&lt;/p&gt;

&lt;p&gt;This is the short, practical guide I wish someone had handed me before that day. No theory you will never use. Just how to back up your project files and your database properly, on a schedule, somewhere safe, so a dead server is an annoyance instead of a funeral.&lt;/p&gt;

&lt;h2&gt;
  
  
  The one rule that actually matters: 3-2-1
&lt;/h2&gt;

&lt;p&gt;You will see it everywhere because it works.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;3&lt;/strong&gt; copies of your data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2&lt;/strong&gt; different places&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;1&lt;/strong&gt; of them off the server&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most people get the first two by accident and miss the one that counts. A backup sitting on the same server as your live site is not a backup. It is a second copy waiting to die in the same crash, the same hack, the same accidental &lt;code&gt;rm -rf&lt;/code&gt;, the same suspension. If your backup can be deleted by whatever kills your server, it was never real.&lt;/p&gt;

&lt;p&gt;Off-site is the whole game. Everything below builds toward it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Back up the database the right way
&lt;/h2&gt;

&lt;p&gt;Files you can usually re-download or rebuild. The database is the irreplaceable part. It is your users, your orders, your content, the actual value of the thing. Start here.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MySQL or MariaDB:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mysqldump &lt;span class="nt"&gt;--single-transaction&lt;/span&gt; &lt;span class="nt"&gt;--quick&lt;/span&gt; &lt;span class="nt"&gt;--routines&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-u&lt;/span&gt; youruser &lt;span class="nt"&gt;-p&lt;/span&gt; yourdatabase | &lt;span class="nb"&gt;gzip&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; db-&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; +%F&lt;span class="si"&gt;)&lt;/span&gt;.sql.gz
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The flags matter more than they look. &lt;code&gt;--single-transaction&lt;/code&gt; takes a clean, consistent snapshot without locking your tables, so your live site keeps running while the dump happens. &lt;code&gt;--quick&lt;/code&gt; streams rows instead of loading the whole table into memory. &lt;code&gt;gzip&lt;/code&gt; shrinks a text dump by ten times or more.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PostgreSQL:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pg_dump &lt;span class="nt"&gt;-U&lt;/span&gt; youruser &lt;span class="nt"&gt;-Fc&lt;/span&gt; yourdatabase &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; db-&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; +%F&lt;span class="si"&gt;)&lt;/span&gt;.dump
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;-Fc&lt;/code&gt; custom format is already compressed and lets you restore selectively later.&lt;/p&gt;

&lt;p&gt;Test the restore now, not during a fire. A backup you have never restored is a rumor, not a backup.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;gunzip&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; db-2026-06-05.sql.gz | mysql &lt;span class="nt"&gt;-u&lt;/span&gt; youruser &lt;span class="nt"&gt;-p&lt;/span&gt; a_scratch_database
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If it loads into a throwaway database cleanly, you have a real backup. If it errors, you just found out today instead of on your worst day.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Back up the files that cannot be regenerated
&lt;/h2&gt;

&lt;p&gt;Do not tar up your entire server. Most of it is reinstallable. Back up the parts that are truly yours:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User uploads and media (&lt;code&gt;storage/app&lt;/code&gt;, &lt;code&gt;wp-content/uploads&lt;/code&gt;, your public upload dirs)&lt;/li&gt;
&lt;li&gt;Config and secrets (&lt;code&gt;.env&lt;/code&gt;, &lt;code&gt;wp-config.php&lt;/code&gt;, anything with keys in it)&lt;/li&gt;
&lt;li&gt;Custom code that is not already in git&lt;/li&gt;
&lt;li&gt;Your email, if it lives on the same server. Mail is just files: your inbox sits in a maildir, often under your home or &lt;code&gt;/var/mail&lt;/code&gt;. Back that folder up and a wiped mailbox becomes recoverable instead of gone.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;tar&lt;/span&gt; &lt;span class="nt"&gt;-czf&lt;/span&gt; files-&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; +%F&lt;span class="si"&gt;)&lt;/span&gt;.tar.gz &lt;span class="se"&gt;\&lt;/span&gt;
  storage/app &lt;span class="se"&gt;\&lt;/span&gt;
  .env &lt;span class="se"&gt;\&lt;/span&gt;
  public/uploads
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Skip the noise. Your &lt;code&gt;node_modules&lt;/code&gt;, &lt;code&gt;vendor&lt;/code&gt;, and framework core are a &lt;code&gt;composer install&lt;/code&gt; or &lt;code&gt;npm install&lt;/code&gt; away. Backing them up just makes the archive huge and slow for zero benefit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Automate it, because you will forget
&lt;/h2&gt;

&lt;p&gt;A backup you have to remember to run is a backup that will not exist the week you need it. Put it on a schedule and walk away.&lt;/p&gt;

&lt;p&gt;Drop your dump and tar commands into a small script, then add one cron line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# back up every night at 2am&lt;/span&gt;
0 2 &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; /home/youruser/backup.sh &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; /home/youruser/backup.log 2&amp;gt;&amp;amp;1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That log on the end is not optional. A silent cron job that quietly broke three weeks ago is how people end up with a folder full of zero-byte files. Log it, and glance at the log once in a while.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Get it off the server
&lt;/h2&gt;

&lt;p&gt;This is the step everyone skips and everyone regrets. A backup on the same box is gone the moment the box is gone. Push it somewhere with no connection to your hosting account: object storage, a different provider, anywhere the failure of your server cannot reach.&lt;/p&gt;

&lt;p&gt;If you are on raw cloud storage, that means wiring up credentials, install tooling, lifecycle rules, and praying you never leak a key that has write access to everything you own. It is doable. It is also a lot of moving parts to get right and keep right, forever, for every server you run.&lt;/p&gt;

&lt;p&gt;Which is the honest reason I eventually stopped doing it by hand.&lt;/p&gt;

&lt;h2&gt;
  
  
  The shortcut: let an agent do all four steps
&lt;/h2&gt;

&lt;p&gt;I run &lt;a href="https://codedhost.vip" rel="noopener noreferrer"&gt;CodedHost&lt;/a&gt;, and the thing I kept wishing existed is the thing we ended up building: a small agent you drop onto any server that does every step above on its own.&lt;/p&gt;

&lt;p&gt;You install it with one line, point it at your databases and folders once, and from then on it dumps, compresses, and ships an off-site copy every night without you touching it. It runs on a full root VPS and on shared hosting like cPanel or Namecheap where you have no root at all. It does not even matter what your site is built with.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://codedhost.vip/agent/install.sh | &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;command&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="nb"&gt;sudo&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt; bash &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; &amp;lt;your-agent-id&amp;gt; &amp;lt;your-secret&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The part I care about most: the storage is completely separate from your hosting. The agent never holds the keys to it. Each run it checks in, gets a one-time upload link good for a few minutes, ships the file, and the link expires. Nothing permanent sits on your server to leak. And because the backup lives somewhere independent, it is still there and still downloadable even on a day your host suspends you, or our own site is having a bad time. Your data does not depend on anyone's uptime, including ours.&lt;/p&gt;

&lt;p&gt;When you need it back, it hands you the file and gets out of the way. It will never reach into your live database and overwrite it on a guess. You restore, on your terms.&lt;/p&gt;

&lt;p&gt;That is the whole idea: 3-2-1 done for you, including the off-site copy that is the only part that ever really saves you.&lt;/p&gt;

&lt;p&gt;You can read exactly how it works, or grab it, here: &lt;strong&gt;&lt;a href="https://codedhost.vip/server-backup" rel="noopener noreferrer"&gt;codedhost.vip/server-backup&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The one-line version
&lt;/h2&gt;

&lt;p&gt;Back up your database with &lt;code&gt;--single-transaction&lt;/code&gt;. Back up only the files you cannot regenerate. Put it on cron with a log. And get a copy off the server, because the copy that lives somewhere else is the only one that will ever save you.&lt;/p&gt;

&lt;p&gt;Do it by hand or let something do it for you. Just do not be the person learning this lesson the expensive way. I already took that one for you.&lt;/p&gt;

</description>
      <category>backup</category>
      <category>devops</category>
      <category>linux</category>
      <category>database</category>
    </item>
  </channel>
</rss>
