Jesse Laprade

Setting up a paste service with Vim, rsync, and nginx

This page guides you through setting up a paste service with Vim, rsync, and nginx. This guide uses Vim’s :TOhtml command to convert source code to HTML with syntax highlighting.

Page overview

Reasoning for this guide

I’m writing this guide, not only because it’s a really basic way to show code to friends, but also because I love writing my own little tools and learning about web servers and network infrastructure.

Page conventions

Assumptions

This guide assumes:

Requirements on your local machine

Preparing your server

You need to create a directory for the files you paste, a landing page in case users decide to navigate to your paste. subdomain, configure nginx to serve the paste directory, and setup SSL/TLS for your domain.

This section consists of the following topics:

Setting up DNS records on DigitalOcean

Setting up DNS records for paste.example.com allows DigitalOcean to know about your new subdomain.

To setup DNS records on DigitalOcean
  1. Add an A record for paste.example.com to your DigitalOcean droplet
  2. Add an AAAA record for paste.example.com to your DigitalOcean droplet

Note: You may need to wait a few minutes for the DNS records to update.

Creating a new domain directory

To share the files you have pasted, you need to create a directory for your files to reside in.

To create a new domain directory
  1. SSH into your server
  2. Run sudo mkdir -p /var/www/paste.example.com
  3. Run sudo chown -R $USER:$USER /var/www/paste.example.com
  4. Run sudo chmod -R 755 /var/www/paste.example.com

Configuring nginx

You need to setup a subdomain for your domain in nginx. In this guide, we use the domain, example.com, and the subdomain, paste.. The full URL for our pasting service is paste.example.com.

Ensure you replace example.com with your own domain when following this guide.

To configure nginx
  1. Add the following in /etc/nginx/sites-available/paste.example.com as root:

    server {
        server_name paste.example.com;
    
        root /var/www/paste.example.com;
        index index.txt;
    
        location / {
            try_files $uri $uri/ =404;
        }
    }
  2. Run the following command:

    sudo ln -s /etc/nginx/sites-available/paste.example.com /etc/nginx/sites-enabled/paste.example.com
  3. Run sudo systemctl restart nginx

Setting up your paste service domain with certbot

Setting up SSL/TLS with certbot stops browsers from telling the user they are on an insecure connection.

To setup your paste service domain with certbot
  1. Run sudo certbot
  2. Follow the prompts
  3. Run sudo systemctl restart nginx

Preparing your local machine

You need to create a local paste directory, and add a function and command to your ~/.vimrc file.

This section consists of the following topics:

Creating a paste directory

The paste directory allows you to keep a collection of files locally. The local paste directory synchronizes with your remote paste directory using rsync.

To create a paste directory
  1. Run mkdir -p ~/dev/paste

Creating a landing page for the paste service

Users may get curious and wander away from paste.example.com/some-file.py. One of the places they may go is paste.example.com, so creating a landing page for this URL is nicer than getting a 404 error.

To create a landing page for the paste service
  1. Run the following command:

    echo "Hey there! It looks like you found my paste service! Unfortunately, there isn't much here!" > ~/dev/paste/index.txt

    Warning: If you delete the ~/dev/paste/index.txt file, the your landing page disappears the next time you synchronize your ~/dev/paste directory.

Setting up a generic file-pasting script

This script not only supports code snippets with syntax highlight, but it also supports generic file pasting, such as the pasting of images, gifs, videos, etc.

To setup a generic file-pasting script
  1. Add the following to a file called pupload:

    #!/bin/sh
    file="$@"
    domain="https://paste.example.com/"
    
    cp $file ~/dev/paste/$file
    cd ~/dev/paste
    rsync -a --delete ./$file user@example.com:/var/www/paste.example.com/
    echo "Paste URL: $domain$file"
  2. Run chmod u+x pupload

  3. Move the pupload to a directory on your $PATH

Setting up a generic file-pasting script for plaintext files

This script appends a .txt to the end of the filename, so other people can view the file in their browser without downloading the file.

To setup up a generic file-pasting script for plaintext files
  1. Add the following to a file called ptxt:

    file="$@"
    filetxt=$file.txt
    domain="https://paste.example.com/"
    
    cp $file ~/dev/paste/$filetxt
    cd ~/dev/paste
    rsync -a --delete ./$filetxt user@example.com:/var/www/paste.example.com/
    echo "Paste URL: $domain$filetxt"
  2. Run chmod u+x ptxt

  3. Move the ptxt to a directory on your $PATH

Setting up a generic file-synchronizing script

When removing or modifying files in your ~/dev/paste/ directory, you must synchronize after, so all files on your server update.

To setup a generic file-synchronizing script
  1. Add the following to a file called psync:

    #!/bin/sh
    cd ~/dev/paste
    rsync -a --delete ./ user@example.com:/var/www/paste.example.com/
    echo "Files synchronized"
  2. Run chmod u+x psync

  3. Move the psync to a directory on your $PATH

Setting up Vim

Vim commands make uploading and synchronizing your paste directory to your remote server convenient. They remove the need to exit Vim to run shell scripts.

To setup Vim
  1. Add the following contents to your ~/.vimrc:

    function! PasteSync()
      call system('psync')
    endfunction
    
    function! PasteUpload()
      TOhtml
      let filename = expand("%:t")
      silent! execute 'write!' '~/dev/paste/' . filename
      call PasteSync()
      q!
      echo 'Paste link: https://paste.example.com/' . filename
    endfunction
    
    command PasteSync call PasteSync()
    command PasteUpload call PasteUpload()

    Note: You need to replace user in the PasteSync() function with your own SSH username.

Using the paste service

You can use the two commands from the previous section to upload and synchronize files to your remote paste directory.

This section consists of the following topics:

Uploading a code snippet from Vim

The Vim configuration from the previous section allows us to upload Vim buffers as code snippets.

To uploading a code snippet
  1. Open a file in Vim
  2. Run :PasteUpload
  3. Share the URL generated at the bottom of the screen

Uploading a generic file

The pupload script from the Setting up a generic file-pasting script section allows you to paste any file to your server.

To upload a generic file
  1. Run pupload your-file

Uploading a generic file in plaintext format

Sometimes, you want to view the contents of a file in your browser. Adding “.txt” at the end of a filename allows your browser to render the contents of the file if it is in a plaintext format.

To upload a generic file in plaintext format
  1. Run ptxt your-file

Note: This appends a .txt to your file. So, if your file is named code.py, the file is renamed to code.py.txt. When you click the link that is generated, you can view the contents of the file in your browser, instead of being prompted to download the file.

Removing a file

rsync removes the need to SSH into your server to remove a directory by synchronizing a directory’s state using the --delete flag.

To remove a file
  1. cd ~/dev/paste
  2. rm file-you-want-to-remove.py
  3. Run psync