Server Migration: 6.0.7+Windows+MySQL to 6.3.4+Linux+MariaDB

There is no guide out there that describes a migration from a Windows Server to a Linux Server when using MySQL, only just the quickshot from the manual page when using the internal SQLite databases. So I will post my steps here as a help to anyone who might face the same quest…

Plus we will be using a dedicated data disk on the source server as well as on the destination server.

In addition, we will be using a setup where seafile will NOT be served from the / webroot as there is also other stuff on the same machine / proxy.

To make it complete, we will also be updating from an older to the current
version. So this will be something like an up-cross-grade migration.

Hints:

  • This is mainly a raw guide for myself, everyone out there following it should
    read this with a wake mind and adapt to your own special setup.
    You should also have a raw understanding of what you are doing and you should
    also have at least basic knowledge of Linux, SQL and Webservers / proxies.
  • The have been spaces added between http and :// for not being embedded as links
  • I ran into different issues which are not covered here, this is now the working
    straight-forward way that remained in the end.
    I always had the old Windows installation of SeaFile in the back ready to be
    started up again in case that the whole procedure would fail - gives a lot of
    insurance.
  • I cannot be taken liable for anything you do when following these steps,
    especially data loss.
  • I deeply disagree with the deprecation and discontinuing of the Windows version
    of SeaFile server. I am developer myself and cross-platform development is not
    that hard - Java (at work and at home) and C# (in an earlier job, mainly at
    home now) in my case; but the usage of Python (and not some native code) should
    also make it possible for SeaFile. It just takes a bit of wakeness and
    discipline while coding.
  • The guide contains comments that sometimes include sarcasm or stinging mockery.
  • The reason why I’m doing this is because I already had a Linux machine running
    here in form of a RasPi with Raspbian/PiHole (great software, by the way). Both
    the PiHole and the SeaFile server will be summarized into one new machine.
  • Stuff written inside of () are comments, explanations or non-command
    instructions. Again, read with a wake mind.

From:

  • SeaFile 6.0.7 CE
  • MySQL Server CE 5.7.25 (plus MySQL Workbench CE 8.0.15)
  • Windows Server 2012 R2 on existing hardware
  • IIS as Proxy (with some other stuff; SeaFile on https ://xxx.yyy.zzz/seafile/)
  • SeaFile program at C:\ServerData\SeafileServer (on system SSD)
  • SeaFile data at E:\seafile-server (on dedicated HDD; this is also where seafserv.ini points to)
  • roughly ~1TB of data to be migrated

To:

  • SeaFile 6.3.4 CE
  • MariaDB 10.3.14
  • Ubuntu Server LTS 18.04.2 on new hardware
  • SeaFile program at /srv/seafile/ (on system SSD)
  • SeaFile data at /data/seafile-data/ (on dedicated HDD)
  • IIS as Proxy on existing Windows Server 2012 R2 will remain there
    (there are other things served from here too; I want no discussion on that decision)

Assumed prerequisites:

  • fresh installation of Ubuntu Server on new hardware is done
  • SSH enabled; as the server will later be running “headless” with power+LAN only
  • systems are updated to latest version
  • fixed IPv4 and IPv6 addresses have been configured
  • whatever else software and services are installed and configured (not covered here!)
  • dedicated data HDD is already formatted into one large ext4 partition
    (I use gparted live for this; I avoid stupid shell stunts wherever I can)
  • seafile-server_6.3.4_x86-64.tar.gz is already downloaded and copied to ~
    (I used a regular browser and WinSCP on another box; again: I avoid stupid shell stunts…)

1.) Data HDD preparation

  • sudo mkdir /data
    (this will be the dir for mount point)
  • sudo blkid
    (copy UUID of desired data partition; WITHOUT the enclosing “”; NOT the PARTUUID)
  • sudo nano /etc/fstab
    (yet again, I avoid stunts with vi, vim oder ever more stupid tools)
    (add line at the end)
    UUID=xyz /data ext4 defaults 0 2
    (where xyz is the copied UUID from before)
    (save and exit)
  • sudo mount -a
    (should finish without error)
  • ll /data/
    (should present the lost+found that exists on ext4 partitions by default)

2.) Install and prepare MariaDB

  • sudo apt-get remove mariadb-server
    (just to make sure old versions are absent)
  • sudo apt-get install software-properties-common
    (just to make sure it is there)
  • sudo apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xF1656F24C74CD1D8
    (imports MariaDB repo key)
  • sudo add-apt-repository ‘deb [arch=amd64] http ://mirror.zol.co.zw/mariadb/repo/10.3/ubuntu bionic main’
    (adds MariaDB repo)
  • sudo apt update
    sudo apt -y install mariadb-server mariadb-client
    (installs Server and Tools; give secure DB-root password during installation)
  • mysql -u root -p
    (confirm with DB-root password)
    GRANT ALL PRIVILEGES ON . TO ‘root’@‘192.168.%’ IDENTIFIED BY ‘xyz’ WITH GRANT OPTION;
    (allow remote access for DB-root from other machines in LAN; give secure DB-root password here instead of xyz)
    QUIT
  • (I did not need to change the bind address of MariaDB, that was already OK)

3.) Prepare DBs for SeaFile

  • mysql -u root -p
    (confirm with DB-root password)
    CREATE DATABASE dbccnet;
    CREATE DATABASE dbseafile;
    CREATE DATABASE dbseahub;
    (creates the databases itself)
    CREATE USER ‘dboSeaFile’@’%’ IDENTIFIED BY ‘xyz’;
    (creates a user exclusive for SeaFile; give a secure DB password here instead of xyz)
    GRANT ALL ON dbccnet.* TO ‘dboSeaFile’@’%’;
    GRANT ALL ON dbseafile.* TO ‘dboSeaFile’@’%’;
    GRANT ALL ON dbseahub.* TO ‘dboSeaFile’@’%’;
    (grants privileges to the user on the DBs)
    QUIT
  • mysql -u dboSeaFile -p
    (confirm with user’s DB password)
    SHOW DATABASES;
    (should list the DBs created earlier, plus information_schema)
    QUIT

4.) Installation of new, empty SeaFile Server

  • sudo apt -y install python python-pip python-pil python-ldap python-urllib3 libpython3.6 python-setuptools python-mysqldb python-memcache python-requests ffmpeg
    (installs requirements, python mainly)

  • sudo tar -xvf seafile-server_6.3.4_x86-64.tar.gz -C /srv
    (unpacks the archive)

  • sudo mv /srv/seafile-server-6.3.4 /srv/seafile
    (renames directory)

  • cd /srv/seafile/

  • sudo ./setup-seafile-mysql.sh
    (press Enter to confirm)
    (give any server name, propably the same as on the old server)
    (give IPv4 address of server for now)
    (give /data/seafile-data as data dir)
    (leave default port)
    (2 for existing DBs)
    (leave localhost for mysql server)
    (leave default port for mysql)
    (give dboSeaFile for mysql user)
    (give user’s DB password)
    (give dbccnet)
    (give dbseafile)
    (give dbseahub)
    (press Enter to confirm)

  • sudo ./seafile.sh start
    (starts manually once)

  • sudo ./seahub.sh start
    (starts manually once)
    (give SeaFile admin mailaddress)
    (give SeaFile admin password)

  • (login with browser on http ://newserverip:8000/ and SeaFile admin credentials, everything should be fine)

  • sudo ./seahub.sh stop
    (stops manually)

  • sudo ./seafile.sh stop
    (stops manually)

  • sudo nano /etc/systemd/system/seafile.service
    (Add the following:)
    [Unit]
    Description=Seafile
    Wants=network-online.target mariadb.service
    After=network.target network-online.target mariadb.service

    [Service]
    Type=forking
    ExecStart=/srv/seafile-server-latest/seafile.sh start
    ExecStop=/srv/seafile-server-latest/seafile.sh stop

    [Install]
    WantedBy=multi-user.target
    (save and exit)
    (creates systemd config for seafile)

  • sudo nano /etc/systemd/system/seahub.service
    (Add the following:)
    [Unit]
    Description=Seafile
    Wants=network-online.target
    After=network.target network-online.target seafile.service

    [Service]
    Type=forking
    ExecStart=/srv/seafile-server-latest/seahub.sh start
    ExecStop=/srv/seafile-server-latest/seahub.sh stop

    [Install]
    WantedBy=multi-user.target
    (save and exit)
    (creates systemd config for seahub

  • sudo systemctl daemon-reload
    (refreshes)

  • sudo systemctl start seafile && sudo systemctl enable seafile
    (starts and enables seafile by systemd)

  • sudo systemctl start seahub && sudo systemctl enable seahub
    (starts and enables seahub by systemd)

  • sudo reboot
    (restarts whole system)
    (login again afterwards)

  • sudo systemctl status seafile
    (should give green status - running)

  • sudo systemctl status seahub
    (should give green status - running)

  • sudo systemctl stop seahub
    (stops seahub by systemd)

  • sudo systemctl stop seafile
    (stops seafile by systemd)

  • sudo systemctl disable seahub
    (disables seahub by systemd)

  • sudo systemctl disable seafile
    (disables seafile by systemd)

5.) Data migration

  • sudo -s
    (grants permanent root, required for a lot of the following commands)

  • cd /data/seafile-data/

  • rm -r *
    (removes all contents from data dir)

  • (connect to MariaDB server with DB-root via MySQL Workbench)
    (drop all existing tables from dbccnet; I don’t want to do that load of tables one-by-one via shell stunts…)
    (drop all existing tables from dbseafile; I don’t want to do that load of tables one-by-one via shell stunts…)
    (drop all existing tables from dbseahub; due to foreign-key-constraints, you will get an error message in the first try; refresh and drop the remaining tables in a second run)

  • (switch over to old Windows Server)
    (exit and disable autostart of SeaFile notification applet in tray, as this would also start the service on restart)
    (stop and disable SeaFile service)
    (read-only-share E:\seafile-server as “sese” under a user account)
    (make sure the user account has the accoring rights on the filesystem)
    (read-only-share C:\ServerData\SeafileServer\seahub\media\avatars as “seav” under a user account)
    (make sure the user account has the accoring rights on the filesystem)
    (open command line and change to MySQL Workbench dir)
    mysqldump.exe --user=root --host=localhost --protocol=tcp --port=3306 --default-character-set=utf8 --single-transaction=TRUE --databases “dbseahub” “dbseafile” “dbccnet” --column-statistics=0 -p > E:\seafile-server\dbsdump.sql
    (enter DB-root password of old MySQL server)
    (exports the the DBs to a dump file; I would have used the Workbench, but that fails against the old 5.7.x MySQL server; only command line allows --column-statistics=0)

  • (open the dbsdump.sql in a good editor; I would recommend Notepad++)
    (replace all of the equivalent lower-case occurrences by the following ones:)
    `Branch`
    `GarbageRepos`
    `InnerPubRepo`
    `OrgQuota`
    `OrgUserQuota`
    `Repo`
    `RepoFileCount`
    `RepoGroup`
    `RepoHead`
    `RepoHistoryLimit`
    `RepoOwner`
    `RepoSize`
    `RepoTokenPeerInfo`
    `RepoTrash`
    `RepoUserToken`
    `RepoValidSince`
    `SharedRepo`
    `SystemInfo`
    `UserQuota`
    `UserShareQuota`
    `VirtualRepo`
    `WebAP`
    `Binding`
    `EmailUser` (watch out where replacing this one as it also occurrs as a column name; only replace where the table name is meant)
    `Group`
    `GroupDNPair`
    `GroupUser`
    `LDAPUsers`
    `Organization`
    `OrgGroup`
    `OrgUser`
    `UserRole`
    (use case-insensitive search+replace so you don’t manually have to type the lower-case version of every affected table names)
    (Include the leading and trailing ` to avoid some of the names occurring elsewhere (e.g. as part of other names or as names of columns) from being replaced too)
    (save and exit)
    (this is required as the default settings of the Windows version of MySQL convert to all-lowercase names for the tables in ccnet and seafile DBs, whereas the Linux version uses the spelling from the list before as stated in all of SeaFile’s code)
    (what an ugly sh*t… whoever made that decision for MySQL to use the case (in-)sensitivity of the underlying filesystem should be slapped a thousand times! DB contents should be completely independent and portable between whatever OS hosting the DB server…)

  • (copy mysql dump over to new machine’s ~ dir by WinSCP)

  • (switch over to new Ubuntu Server)

  • cd ~

  • mysql -u root -p < dbsdump.sql
    (confirm with DB-root password)
    (imports the dump of the three DBs)

  • apt -y install smbclient
    (installs smbclient required for access to the share on the old server)

  • cd /srv/

  • mv ccnet/ ccnet-backup
    (rename original ccnet dir)

  • cp -r conf/ conf-backup
    (make backup copy of original config dir)

  • mkdir ccnet
    (create new, empty ccnet dir)

  • mkdir conf-mig
    (create new dir for conf folder to be migrated)

  • cd /srv/ccnet/

  • smbclient //oldserverip/sese -U xyz
    (opens the smbclient connected to the share, xyz has to be replaced with the sharing windows user account)
    (confirm with sharing user’s password)
    (in the sub-shell enter the following:)

    recurse ON
    prompt OFF
    cd ‘ccnet’
    mget *
    exit
    (this should have copied all the ccnet files from the old to the new server)

  • cd /srv/conf-mig/

  • smbclient //oldserverip/sese -U xyz
    (opens the smbclient connected to the share, xyz has to be replaced with the sharing windows user account)
    (confirm with sharing user’s password)
    (in the sub-shell enter the following:)
    mask “”
    recurse ON
    prompt OFF
    cd ‘conf’
    mget *
    exit
    (this should have copied all the conf files from the old to the new server)

  • cd /srv/seahub-data/

  • mv avatars/ avatars-backup
    (rename the symlink; this one points to an invalid dir anyway…)

  • mkdir avatars
    (create a new one here)

  • chmod ogua+w avatars
    (give additional rights to new folder; matching the rights of the original symlink)

  • cd /srv/seafile-data/avatars/

  • smbclient //oldserverip/seav -U xyz
    (opens the smbclient connected to the share, xyz has to be replaced with the sharing windows user account)
    (confirm with sharing user’s password)
    (in the sub-shell enter the following:)
    mask “”
    recurse ON
    prompt OFF
    mget *
    exit
    (this should have copied all the conf files from the old to the new server)

  • cd /srv/

  • cp ccnet-backup/seafile.ini ccnet/
    (copies the seafile.ini which points to the data directory)

  • nano conf/ccnet.conf
    (insert values for USER_NAME, ID and NAME from the file located at conf-mig/ccnet.conf
    (leave all other custom values unchanged now, we will return to this later when everything else works)
    (save and exit)

  • nano conf/seahub_settings.py
    (insert value for SECRET_KEY from the file located at conf-mig/seahub_settings.py)
    (leave all other custom values unchanged now, we will return to this later when everything else works)
    (save and exit)

  • cd /data/seafile-data/

  • smbclient //oldserverip/sese -U xyz
    (opens the smbclient connected to the share, xyz has to be replaced with the sharing windows user account)
    (confirm with sharing user’s password)
    (in the sub-shell enter the following:)
    mask “”
    recurse ON
    prompt OFF
    cd ‘seafile-data’
    mget *
    exit
    (this should have copied all the data files from the old to the new server; yes, this may take some time with a load of files…)

6.) Upgrade imported databases to current version

  • (you could do all the following steps in this chapter with a second SSH login while the data files are copying)
  • cd /srv/seafile/upgrade/sql/6.1.0/mysql/
  • mysql -u root -p dbseahub < seahub.sql
    (confirm with DB-root password)
    (applies the SQL statements from the file to seahub DB)
  • cd /srv/seafile/upgrade/sql/6.2.0/mysql/
  • mysql -u root -p dbccnet < ccnet.sql
    (confirm with DB-root password)
    (applies the SQL statements from the file to seahub DB)
  • mysql -u root -p dbseahub < seahub.sql
    (confirm with DB-root password)
    (applies the SQL statements from the file to seahub DB)
  • cd /srv/seafile/upgrade/sql/6.3.0/mysql/
  • mysql -u root -p dbccnet < ccnet.sql
    (confirm with DB-root password)
    (applies the SQL statements from the file to seahub DB)
  • mysql -u root -p dbseafile < seafile.sql
    (confirm with DB-root password)
    (applies the SQL statements from the file to seahub DB)
  • mysql -u root -p dbseahub < seahub.sql
    (confirm with DB-root password)
    (applies the SQL statements from the file to seahub DB)

7.) Check that everything works so far

  • cd /srv/seafile/
  • sudo ./seafile.sh start
    (starts manually once)
  • sudo ./seahub.sh start
    (starts manually once)
  • (login with browser on http ://newserverip:8000/ and any of the credentials from the old installation)
    (test down-/upload, sharing, etc. etc.)
    (logout)
  • (test-connect a new installation of the sync client or whatever other clients are in use locally and test them)
  • sudo ./seahub.sh stop
    (stops manually)
  • sudo ./seafile.sh stop
    (stops manually)

8.) Re-configure SeaFile and IIS proxy

  • (re-apply any eventual other settings to the config files from earlier)
  • sudo nano /srv/conf/ccnet.conf
    (make sure the SERVICE_URL is set to the external one, like https ://xxx.yyy.zzz/seafile/)
    (save and exit)
  • sudo nano /srv/conf/seahub_settings.py
    (make sure the following lines are contained:)
    ## Needed as the proxy will be on a different machine
    ## and cannot serve the static content itself
    SERVE_STATIC = True
    ## Needs to be set for serving static content under a subfolder
    MEDIA_URL = ‘/seafile/media/’
    COMPRESS_URL = MEDIA_URL
    STATIC_URL = MEDIA_URL + ‘assets/’
    ## Needs to be set for serving under subfolder
    SITE_ROOT = ‘/seafile/’
    LOGIN_URL = ‘/seafile/accounts/login/’
    ## Needs to be set for access to seafile via proxy
    FILE_SERVER_ROOT = ‘https ://xxx.yyy.zzz/seafhttp’
    (save and exit)
  • sudo nano /srv/seafile/seahub/seahub/urls.py
    (scroll down to a line containing the following:)
    if settings.SERVE_STATIC:
    (was line #505 for server version 6.3.4)
    (in the block of code below the SERVE_STATIC, replace the following line:)
    media_url = settings.MEDIA_URL.strip(’/’)
    (with the following lines:)
    ## - - - Original code
    ##media_url = settings.MEDIA_URL.strip(’/’)
    ## - - - Begin new code
    media_url = settings.MEDIA_URL
    site_root = settings.SITE_ROOT
    if media_url.startswith(site_root):
        media_url = media_url[len(site_root):]
    media_url = media_url.strip(’/’)
    ## - - - End new code
    (save and exit)
    (this applies a fix required for statically served media to work from /seafile/media/)
  • sudo systemctl start seafile && sudo systemctl enable seafile
    (starts and enables seafile by systemd)
  • sudo systemctl start seahub && sudo systemctl enable seahub
    (starts and enables seahub by systemd)
  • (switch over to old Windows Server)
  • (open the IIS manager and go to the according site)
  • (remove the statically served /media/ folder)
  • (edit existing url rewrite rule from:)
    seafhttp/(.*) --> http ://127.0.0.1:8082/{R:1}
    (to:)
    seafhttp/(.*) --> http ://newserverip:8082/{R:1}
    (save rule)
  • (edit exist url rewrite rule from:)
    seafile/(.*) --> http ://localhost:8000/seafile/{R:1}
    (to:)
    seafile/(.*) --> http ://newserverip:8000/seafile/{R:1}
    (save rule)
  • (switch over to new Ubuntu Server)

9.) Cleanups

  • cd /srv/
  • rm -r ccnet-backup/
    (delete backup of original ccnet dir from initial installation)
  • rm -r conf-backup/
    (delete backup of original conf dir from initial installation)
  • rm -r conf-mig/
    (delete backup of migrated conf dir from old server)
  • (switch over to old Windows Server)
  • (uninstall / remove seafile installation from old server)

[EDIT on 2019-07-30]

minor typos

updated comment where I formerly blamed SeaFile code to be the cause of DB table name upper/lower case differences between Windows and Linux. In the meantime, I learned that this was caused by the differing default settings of MySQL on the both settings. I’m verry sorry I blamed the wrong suspect in the first place.

2 Likes

In the meantime, I was also able to update the migrated installation to 7.0.3CE some weeks ago and now to 7.0.4CE.

However, there were some special actions required for the scenario used here which I will shortly describe:

  • stop both seahub and seafile daemons first

  • for unpacking the server*.tar.gz, again use a command like
    sudo tar -xvf seafile-server_7.0.4_x86-64.tar.gz -C /srv

  • follow the steps for the according major / minor / maintenance update described in https://manual.seafile.com/deploy/upgrade.html

  • After the 6.3.4-to-7.0.3 update, I had to re-edit the bind address from 127.0.0.1 (localhost only) to 0.0.0.0 (accessible from everywhere including reverse proxy on different machine) in the gunicorn.conf by using
    sudo nano /srv/conf/gunicorn.conf

  • After every update, I have to re-apply the fix for the statically served media to work from /seafile/media that I already described in the original posting:
    sudo nano /srv/seafile/seahub/seahub/urls.py
    (scroll down to a line containing the following:)
    if settings.SERVE_STATIC:
    (in the block of code below the SERVE_STATIC, replace the following line:)
    media_url = settings.MEDIA_URL.strip(’/’)
    (with the following lines:)
    ## - - - Original code
    ##media_url = settings.MEDIA_URL.strip(’/’)
    ## - - - Begin new code
    media_url = settings.MEDIA_URL
    site_root = settings.SITE_ROOT
    if media_url.startswith(site_root):
        media_url = media_url[len(site_root):]
    media_url = media_url.strip(’/’)
    ## - - - End new code
    (save and exit)

  • start both seafile and seahub daemons in the end

2 Likes