12

Not quite a rant, but it'll devolve in heated debate anyway 😂.

So I was discussing deployment methods with a client's CTO today.

He was fervent on using git for deployment (as in, checkout/pull directly on target host).

I was leaning more on, build npm and web bullshit on the runner, rsync to target host.

Ideally, build shit in the runner, publish to an artifact/package manager, pull that in the target host.

Of course, there are many variables and pros/cons on each side, but would like to hear your opinion.

Comments
  • 2
    I, myself, think that

    - both ensure only partial transfers, meaning you save time there on stuff that is usually the same, so tie there.

    - git forces to perform build steps on the target host, reducing performance during the process. Rsync wins.

    - git allows for more powerful rollback mechanics. Git wins here.

    - rsync avoids headache with properly protecting .git, and other sensitive files. Rsync wins.

    - rsync can collapse a runner in case of multi-target deploys. Git wins here, but poorly done ssh got pull is just as bad.

    I'd rather build in the runner, publish to a versioned artifact repository, and tell targets to install from there through pssh or similar.
  • 9
    I'll try to summarize.

    GIT on remote server: bad idea.
    Pulling requires drilling holes in firewalls and NAT. Plus GIT is a development tool, it shouldn't exist on a remote server. Minimal packages on remote server to reduce attack surface.

    Pushing an artifact: good idea.
    Pushing is easier, as you configure the remote server - the changes for the firewall are easily deployable via e.g. Ansible / Puppet or something like that.

    Important with the artifact is the how it's created.

    An artifact should have a reference, this reference should never be deleted - as in always existing. For GIT this means a GIT commit ID to a branch where history rewrite is completely forbidden.

    An artifact should be best a single file, e.g. a tarball - lots of small files are not only bad regarding transfer speed / time, but a single file also makes things like checksumming way easier.

    https://git-scm.com/docs/...

    GIT archive can do exactly that.

    Best would be to add in e.g. a build job in a CI or the build script to generate a SHA or similar checksum file. just for future reference and making sure that the file is verifiable, as one could never be too careful.

    Regarding transfer: SCP is simplest. SCP doesn't transfer permissions (owner / groups) - which is a good idea, so the remote end gets file correctly created by the user of the connection. User of the connection should be dedicated, non root imho.

    Shell Script for SSH is then simply unpack.

    The runtime (node or stuff like that) could run under the same non-root user used for deployment.

    SSH / SCP rules can be used to restrict the login of the non-root user to keyring only and specific IP address, for security.
  • 0
    @IntrusionCM

    Yes, forgot about git doing badly in hosts without direct internet access.

    Scp and rsync both operate on the same basis, but rsync has serious advantages in terms of diffing and such, and better handling of permissions/users.

    (This might seem a non issue, but so many frameworks require fancy premissions, and it gets worse when committing from windows).

    Of course, archived transfer whenever possible, through tarball or any other.

    This particular client has a private npm registry. Maybe just creating a bogus package in that registry and installing from there with npm (which is already on target host by virtue of node) is a decent middle ground.

    I reckon there's no "right" answer, but I do value the insights since you can always learn something new from other's experiences.
  • 2
    @CoreFusionX rsync is mostly a bandaid.

    If using a tarball, rsync shouldn't be necessary and has no benefit over SCP.

    Regarding permissions: See the reason why I suggest SCP and separate user: the file will get created as the connection user based on the remote umask. This solves a lot of problems while also preventing them.

    NPM is a nasty bitch.

    I usually have a specific, company tailored image for building with NPM. Reason is binary compatibility for the virtual machine running the application - some NPM packages compile C / C++ packages or other shit.

    So by making the build image consistent with the virtual machine, I prevent shit like segfaults due to library version mismatches.

    One can create a Docker Image of the application, e.g. a second layer in the Docker file containing only the necessary files for running the application.

    This does not mean that the remote has to run docker - one can just use docker cp to extract the application folder from the image and create a tarball of it.

    The tarball can then be transferred to the remote and be done with it.

    Notice: I HATE NPM.

    I REALLY REALLY HATE NPM.
  • 0
    Building & packaging for deployment best not on target host (requires extra software installs vs a "dumb" target host with bare minimum) but on build server.

    If no other/ too costly alternatives, pulling on target host ok but never serve the build directly from the git repo subdir (move it to eg /var/www/mysite). Also no git user but pull with a deploy token with read-only permission.
  • 0
    @IntrusionCM

    Absolutely right about native node modules.

    rsync does allow you to specify user, group and permissions irrespective of remote umask and ssh user, which I find useful. But that of course it's mot if you tarball.
  • 0
    Git is for developing app as a team. What kind of madness makes one use git to replace files on the fly on production server?
  • 3
    I once failed a security audit because .git folder where found on the server...
  • 2
    @CoreFusionX @intrusionCM except that SCP is now deprecated in the OpenSSH package and is bound to die.

    https://lwn.net/Articles/835962/

    I too vouch for rsync. Mainly because you should not have any dev tools on your prod servers. And git is a devtool.

    Also, git-pulling means fetching source code, and in order to build it you'll probably need some build tools (which is a no-no in prod) and you'll hog prod server's resources while building it (disk, network (node_modules), CPU, ram), jeopardising prod's performance and even introducing a possibility of a crash.

    git-pull in your build/deployment machine and push it to your target environment's machine with whatever means you have (scp (deprecated), rsync, ansible, puppet, etc.)
  • 0
    Why not a ststic webserver serving basic HTML, specifically HTML5/CSS3/ES6? Much simpler to deploy.
  • 2
    @max19931

    Because that wasn't the question.

    And hardly any application nowadays is static html, css and JavaScript...
  • 0
    @CoreFusionX except landing pages ofc and you could also mistake https://www.travis-ci.com/ for one (spoiler: it's WP)
  • 0
    you did a git checkout to a particular release tag or commit SHA before building right? Isn’t that more or less the same thing?
  • 0
    @Mmmyaa

    Feel obliged to remind that this is not me asking for help or troubleshoot.

    I am perfectly happy with how my deploys work.

    I just wanted to discuss different mechanisms, is all.
Add Comment