<?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: Keeyan Nejad</title>
    <description>The latest articles on DEV Community by Keeyan Nejad (@keeyan).</description>
    <link>https://dev.to/keeyan</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%2F474790%2Fc9b6623a-d3ed-4dea-b488-c6793b4ad75b.png</url>
      <title>DEV Community: Keeyan Nejad</title>
      <link>https://dev.to/keeyan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/keeyan"/>
    <language>en</language>
    <item>
      <title>How to migrate Google Photos to Proton Drive Photos</title>
      <dc:creator>Keeyan Nejad</dc:creator>
      <pubDate>Thu, 07 Dec 2023 18:19:42 +0000</pubDate>
      <link>https://dev.to/keeyan/how-to-migrate-google-photos-to-proton-drive-photos-6lf</link>
      <guid>https://dev.to/keeyan/how-to-migrate-google-photos-to-proton-drive-photos-6lf</guid>
      <description>&lt;p&gt;Proton Drive just released their photo syncing feature on Android. I've been patiently waiting for this since Drive came out.&lt;/p&gt;

&lt;p&gt;In this post I'm going to explain a an easy way to migrate your data from Google Photos to Proton Drive.&lt;/p&gt;

&lt;p&gt;This will get outdated quickly as I'm sure they will integrate a better migration service, but until then this should work.&lt;/p&gt;

&lt;p&gt;First step is to go to &lt;a href="https://takeout.google.com"&gt;takeout.google.com&lt;/a&gt; and download all of your Photos data.&lt;/p&gt;

&lt;p&gt;You will eventually receive an email with a link to download all your photos.&lt;/p&gt;

&lt;p&gt;Once downloaded, you can unzip all your pictures with this command:&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="nv"&gt;UNZIP_DISABLE_ZIPBOMB_DETECTION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;TRUE unzip &amp;lt;takeout-filename.zip&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you have a nested set of directories with many pictures in them. I recommend deleting all directories that don't have a name like &lt;code&gt;Photos from 2010&lt;/code&gt; as the rest are from albums which are likely duplicated in the &lt;code&gt;Photos from XXXX&lt;/code&gt; files.&lt;/p&gt;

&lt;p&gt;Now you will be left with all your photos as well as some json metadata files, which contain some info about when the photos were taken.&lt;/p&gt;

&lt;p&gt;You could now, upload all the photos to Proton Drive via the web interface. Unfortunately, the photos will all be in the wrong order as they are sorted by the file creation date (which will be today) instead of the date the photo was taken. Also some files could have missing timestamp data.&lt;/p&gt;

&lt;p&gt;Thankfully, there is a really cool tool called &lt;a href="https://pypi.org/project/google-photos-takeout-helper/"&gt;google-photos-takeout-helper&lt;/a&gt;. So you can go ahead and install that, and then run this command to sort all the timestamps:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;google-photos-takeout-helper &lt;span class="nt"&gt;-i&lt;/span&gt; Takeout &lt;span class="nt"&gt;-o&lt;/span&gt; FixedTakeout
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will copy all the files to FixedTakeout with the correct metadata.&lt;/p&gt;

&lt;p&gt;Now that this is done, we can finally upload the folder to the Proton Drive Photos service, and they should hopefully be in chronological order.&lt;/p&gt;

&lt;p&gt;At the time of writing this post however, there is an annoying bug with the photo upload feature on the web interface which causes many failures.&lt;/p&gt;

&lt;p&gt;So a better option, would be to copy all these files to your Android device, and select the new folder to be backed up to Photos, in the Drive settings page.&lt;/p&gt;

</description>
      <category>proton</category>
      <category>migrate</category>
      <category>scripting</category>
      <category>googlephotos</category>
    </item>
    <item>
      <title>A Conservative Case for Concerns</title>
      <dc:creator>Keeyan Nejad</dc:creator>
      <pubDate>Tue, 06 Oct 2020 19:55:18 +0000</pubDate>
      <link>https://dev.to/keeyan/a-conservative-case-for-concerns-3p19</link>
      <guid>https://dev.to/keeyan/a-conservative-case-for-concerns-3p19</guid>
      <description>&lt;p&gt;There are many, many articles which condemn the use of concerns in a Rails project, and they all have valid points.&lt;br&gt;
I mostly agree with the arguments, such as them causing Bi-directional dependencies and arbitrarily splitting up code into multiple files.&lt;br&gt;
That said, I think a lot of these articles go too far by claiming you should never use concerns.&lt;/p&gt;

&lt;p&gt;To be clear, if I saw a model that started with 20 concerns being included, I would be... Well, concerned.&lt;br&gt;
That's why I've titles this a &lt;strong&gt;conservative&lt;/strong&gt; case for concerns.&lt;br&gt;
I think they should be used very sparingly, but not avoided like the Coronavirus.&lt;/p&gt;

&lt;p&gt;Namely, I think when a concern does not depend on any specific methods or attributes of a model existing, doesn't contain code that is likely to evolve with business requirements, and could be used in a completely different project, then it's likely a valid use for a concern.&lt;/p&gt;

&lt;p&gt;Recently, I was working on a project where we needed to import related CSV files.&lt;br&gt;
In these files the associations were done based on the name of the record.&lt;br&gt;
For example if we have a CSV file for articles, and each article belongs to an author, the CSV would have an author column which could have the name "Keeyan Nejad".&lt;br&gt;
Then in the authors CSV we would have a name column which would include the names (assume for this example that all authors have a unique name).&lt;/p&gt;

&lt;p&gt;When importing the CSV, the Author model would get a name from the name column.&lt;br&gt;
Then I would import the articles, but when it would come time to associate an Article with an Author all I would have is the authors name, not the ID.&lt;br&gt;
To solve this I would have to write something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="ss"&gt;title: &lt;/span&gt;&lt;span class="n"&gt;csv_row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="ss"&gt;content: &lt;/span&gt;&lt;span class="n"&gt;csv_row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'content'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="ss"&gt;author: &lt;/span&gt;&lt;span class="no"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="n"&gt;csv_row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'author'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This isn't too bad, but then I it turns out that the Authors belong to a country, and instead of having a country ID we have the name of the country.&lt;/p&gt;

&lt;p&gt;So to import the Authors I would have to do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="n"&gt;csv_row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="ss"&gt;country: &lt;/span&gt;&lt;span class="no"&gt;Country&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="n"&gt;csv_row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'country'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I wanted to clean this up a bit and this is where I found a valid use for a Rails concern.&lt;br&gt;
I wanted a way to associate a record by the name rather than by the ID column.&lt;/p&gt;

&lt;p&gt;After a bit of playing around I came up with this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;AssociableByName&lt;/span&gt;
  &lt;span class="kp"&gt;extend&lt;/span&gt; &lt;span class="no"&gt;ActiveSupport&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Concern&lt;/span&gt;

  &lt;span class="n"&gt;included&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;associate_by_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;define_setter_for_model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;define_setter_for_model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;define_method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;_name="&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;reference&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
        &lt;span class="n"&gt;association_class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;class&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reflect_on_association&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;klass&lt;/span&gt;
        &lt;span class="n"&gt;association&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;association_class&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="n"&gt;reference&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="s2"&gt;"Could not find &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; by name &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;reference&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;association&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;nil?&lt;/span&gt;

        &lt;span class="nb"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;="&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;association&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then in the Article model I just add these lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;AssociableByName&lt;/span&gt;
&lt;span class="n"&gt;associate_by_name&lt;/span&gt; &lt;span class="ss"&gt;:author&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What this code will do is create a new setter in the model called &lt;code&gt;author_name=&lt;/code&gt; which will simply get the author ID from their name and create the association.&lt;/p&gt;

&lt;p&gt;With that change, I can then update the importers to work more consistently:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="ss"&gt;title: &lt;/span&gt;&lt;span class="n"&gt;csv_row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="ss"&gt;content: &lt;/span&gt;&lt;span class="n"&gt;csv_row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'content'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="ss"&gt;author_name: &lt;/span&gt;&lt;span class="n"&gt;csv_row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'author'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's it!&lt;br&gt;
Now the article will automatically associate with the Author by the name, rather than having to do the lookup, I also get the added benefit that it will throw an error if the association doesn't exist (which is consistent with &lt;code&gt;author_id&lt;/code&gt; if the ID didn't exist)&lt;/p&gt;

&lt;p&gt;What do you think? I'm happy to be proven wrong and learn why this code isn't a good Concern, so let me know if you have any thoughts!&lt;/p&gt;

</description>
      <category>rails</category>
      <category>ruby</category>
      <category>codequality</category>
    </item>
    <item>
      <title>How to Change PostgreSQL Server with Minimal Downtime</title>
      <dc:creator>Keeyan Nejad</dc:creator>
      <pubDate>Thu, 24 Sep 2020 21:15:50 +0000</pubDate>
      <link>https://dev.to/keeyan/how-to-change-postgresql-server-with-minimal-downtime-573g</link>
      <guid>https://dev.to/keeyan/how-to-change-postgresql-server-with-minimal-downtime-573g</guid>
      <description>&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;In this article you will move your database over to a new server, with only a few seconds of downtime.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before you begin this guide you'll need the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One Ubuntu 20.04 database server running PostgreSQL by following &lt;a href="https://www.digitalocean.com/community/tutorials/how-to-install-and-use-postgresql-on-ubuntu-20-04"&gt;How To Install and Use PostgreSQL on Ubuntu 20.04&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1 - Creating a server
&lt;/h2&gt;

&lt;p&gt;The first step to migrating to a new server, is of course to create a new server instance. You can go through &lt;a href="https://www.digitalocean.com/community/tutorials/how-to-install-and-use-postgresql-on-ubuntu-20.04"&gt;How To Install and Use PostgreSQL on Ubuntu 20.04&lt;/a&gt; again in order to set up the new database server you just created.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2 - Preparing the old database for replication
&lt;/h2&gt;

&lt;p&gt;In order to transfer all the database data to the new server without any data loss or significant down time, you can configure the new server as a &lt;em&gt;Hot Standby&lt;/em&gt; node and then shut down the old server and promote the new server to the primary node when ready.&lt;/p&gt;

&lt;p&gt;To do this you must first SSH into the original server with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh root@old_database_address
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;old_database_address&lt;/code&gt; with the address of the old database server.&lt;/p&gt;

&lt;p&gt;Then edit the file &lt;code&gt;/etc/postgresql/postgresql_version/main/postgresql.conf&lt;/code&gt;, replacing &lt;code&gt;postgresql_version&lt;/code&gt; with the &lt;em&gt;minor version&lt;/em&gt; number running on your server.&lt;/p&gt;

&lt;p&gt;This can be found by running &lt;code&gt;psql --version&lt;/code&gt;. For example, for &lt;code&gt;psql (PostgreSQL) 9.6.17&lt;/code&gt; &lt;code&gt;postgresql_version&lt;/code&gt; will be replaced with &lt;code&gt;9.6&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Append the following lines to the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;wal_level = hot_standby
hot_standby = on
max_wal_senders = 3
max_replication_slots = 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first line will cause the &lt;em&gt;Write Ahead Log&lt;/em&gt; to log information required to run read-only queries on a Hot Standby server. The second line will enable the server to act as a Hot Standby node. This isn't needed yet, but you will be making the same changes to the new server later and it is easier to copy the same configuration rather than making minor changes to each.&lt;/p&gt;

&lt;p&gt;Next, you need to allow access to the new database server for backups, and for the web server by editing &lt;code&gt;/etc/postgresql/postgresql_version/main/pg_hba.conf&lt;/code&gt;, replacing &lt;code&gt;postgresql_version&lt;/code&gt; as before.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;host replication replica old_database_address/32 md5
host replication replica new_database_address/32 md5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace the values as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;old_database_address&lt;/code&gt; should be the IP address of the old database.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;new_database_address&lt;/code&gt; should be the IP address of your new database server&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finally, a new user needs to be created for the new server to be able to access:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;su - postgres &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"psql -c &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;CREATE ROLE replica REPLICATION LOGIN ENCRYPTED PASSWORD 'topsecretpassword';&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;topsecretpassword&lt;/code&gt; with a secure password of your choice.&lt;/p&gt;

&lt;p&gt;This will run an SQL command as the postgres user, which will create a new role.&lt;/p&gt;

&lt;p&gt;Once these changes have been added, the PostgreSQL server should be restarted:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;systemctl restart postgresql.service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should then make the exact same changes to the new database server by repeating step 3 but instead of connecting to the old database you should connect to the new database server.&lt;/p&gt;

&lt;p&gt;This can be done by running the following instead of &lt;code&gt;ssh root@old_database_address&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh root@new_database_address
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;new_database_address&lt;/code&gt; with the IP address of your new database server.&lt;/p&gt;

&lt;p&gt;Now that both databases have been prepared to handle replication, it is time to actually replicate the data on the new database.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3 - Creating the Hot Standby node and transferring the database data
&lt;/h2&gt;

&lt;p&gt;In this step you will set up the new database instance to become a replica of the old server, using the built in Hot Standby node in PostgreSQL. To begin you must log into the new server with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh root@new_database_address
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;new_database_address&lt;/code&gt; with the IP address of the database server.&lt;/p&gt;

&lt;p&gt;In order for a Hot Standby node to receive the data from the original database, first, all its data must be deleted. This can be done by stopping the postgres instance and deleting the &lt;code&gt;/var/lib/postgres/postgresql_version/main/&lt;/code&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;systemctl stop postgresql.service
&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /var/lib/postgresql/postgresql_version/main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As always, replace &lt;code&gt;postgresql_version&lt;/code&gt; with your version of the postgres database.&lt;/p&gt;

&lt;p&gt;The first command will stop the PostgreSQL service from running, and the second will delete all the database data so that it can load the data from the original system.&lt;/p&gt;

&lt;p&gt;Now you can copy the original databases to the new server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;su - postgres
pg_basebackup &lt;span class="nt"&gt;--pgdata&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/var/lib/postgresql/postgresql_version/main/ &lt;span class="nt"&gt;--write-recovery-conf&lt;/span&gt; &lt;span class="nt"&gt;--username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;replica &lt;span class="nt"&gt;--host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;old_database_address &lt;span class="nt"&gt;--xlog-method&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;stream
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don't forget to change the &lt;code&gt;postgresql_version&lt;/code&gt; to your version of PostgreSQL and &lt;code&gt;old_database_address&lt;/code&gt; to the address of the original database.&lt;/p&gt;

&lt;p&gt;The first command will make you the postgres user, and the second command will copy the data from the original server.&lt;/p&gt;

&lt;p&gt;This command has a few switches which need to be set:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--pgdata&lt;/code&gt; switch specifies the directory where you want the data to be saved, the value has been set to the default directory where PostgreSQL databases are stored.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--write-recovery-conf&lt;/code&gt; creates a default &lt;code&gt;recovery.conf&lt;/code&gt; file when finished that makes setting up the server as a Hot Standby node easier.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--username&lt;/code&gt; lets you set the user name you created when creating the new role.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--host&lt;/code&gt;  allows you to specify the hostname of the original server.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--xlog-method&lt;/code&gt; ensures that all the Write Ahead Log files are copied along with the backup.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once you execute this command you should be prompted for the password you created earlier when creating the replica role.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; If this command hangs it could be because there is an internal firewall rule set on the original server preventing access. This can be fixed by whitelisting the IP address added to the &lt;code&gt;pg_hba.conf&lt;/code&gt; file earlier, depending on the original servers firewall settings.&lt;/p&gt;

&lt;p&gt;Now that the new server has been set up as a replica you need to point the web app to the new database server and make the new database server the primary node.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4 - Switching the primary database node to the new database server
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; At this point you have to change the database address on any websites to the new database address and temporarily shut it down&lt;/p&gt;

&lt;p&gt;Now, you must stop the original database server and promote the old one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh root@old_database_address
systemctl stop postgresql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As always replace &lt;code&gt;old_database_address&lt;/code&gt; with the address of your old database.&lt;/p&gt;

&lt;p&gt;This will stop your original database server.&lt;/p&gt;

&lt;p&gt;Next promote the new database server to master. This will make it the primary server so that it can start writing to the database:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh root@new_database_address
su - postgres
pg_ctlcluster postgresql_version main promote
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again, replace &lt;code&gt;new_database_address&lt;/code&gt; with the IP address of the new database, and also replace &lt;code&gt;postgresql_version&lt;/code&gt; with the version of postgres running on the server.&lt;/p&gt;

&lt;p&gt;Now that the old database has been stopped and the new one has been promoted to master, all that needs to be done is to restart any sites which depend on the database.&lt;/p&gt;

&lt;p&gt;Now you should be able to visit your websites and everything should be running as normal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5 - Cleaning up
&lt;/h2&gt;

&lt;p&gt;Once you are satisfied that everything is working, you can shut down your servers on your old cloud provider and update the white listed addresses in PostgreSQL so that only your new server has access.&lt;/p&gt;

&lt;p&gt;To begin, SSH into your database server again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh root@new_database_address
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;new_database_address&lt;/code&gt; with the IP address of your new database server.&lt;/p&gt;

&lt;p&gt;Next you can edit the &lt;code&gt;pg_hba.conf&lt;/code&gt; file and remove the old database and address. Once done editing the file should look something 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;local all postgres peer
local all all peer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that everything is done, you can safely delete the original databases. Once that is done you have completely finished migrating to a new database server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this article you learned how to migrate your database from server to another with minimal down time. This process consisted of copying a database over to the new server using a Hot Standby node, then switching the primary database server, and shutting down the old database server.&lt;/p&gt;

</description>
      <category>postgres</category>
      <category>database</category>
      <category>devops</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
