Hosting Your Own Ghostbin (Spectre) in 2020

A Ghostbin (Spectre) installation doesn't really require a lot of resources. I am currently running it on a system with 4x 2.26GHz CPUs, 8GBs of RAM and a 120GB disk. I've done it on much less though.

Installing Ghostbin (Spectre)

  1. Install your operating system. I used Ubuntu 20.04 Server.
  2. Install Go:
    cd /usr/local
    wget https://dl.google.com/go/go1.14.linux-amd64.tar.gz
    tar -C /usr/local -xzf go1.14.linux-amd64.tar.gz

    Add to the bottom of your /etc/profile file with:

    export PATH=$PATH:/usr/local/go/bin

    You can either also run that at your command prompt or logout and log back in.

  3. Install Mercurial and Python Pygments:
    apt install mercurial python3-pygments
  4. Install ansi2html:
    apt install python-pip
    pip install ansi2html
  5. Install Git, I like to compile it myself so I get the latest version:
    cd /usr/local/src
    apt install autoconf libssl-dev zlib1g-dev libcurl4-openssl-dev tcl-dev gettext
    wget https://github.com/git/git/archive/v2.22.1.tar.gz
    tar zxvf v2.22.1.tar.gz
    cd git-2.22.1/
    make configure
    ./configure --prefix=/usr
    make -j2
    make install
  6. I recommend creating a new user to run your GhostBin code under:
    adduser ghostbin
  7. You should also set a password on the new user account using passwd ghostbin.
  8. Login as your new user account and add the following to your ~/.bashrc file:
    export GOPATH=$HOME/go
  9. Save and exit the file and run source ~/.bashrc.
  10. Next obtain the source code for GhostBin (login as your new user first):
    mkdir -p ~/go/src
    cd $HOME/go/src
    mkdir github.com
    cd github.com
    git clone https://github.com/DHowett/spectre.git
    cd spectre/
  11. At this point your full path should be something like - /home/ghostbin/go/src/github.com/spectre.
  12. Run go get.
  13. Run go build.
  14. Run which pygmentize. It should return /usr/bin/pygmentize. If not, no problem, just copy the path.
  15. You'll also want to run which ansi2html which should return /usr/local/bin/ansi2html. Again, if it doesn't no big deal, just copy the path.
  16. Update the languages.yml file with the paths for pygmentize which should be on line 6. Also update the path for ansi2html which should be on line 23. Save and exit. Here's my languages.yml up to line 25 to give you an example:
    formatters:
      default:
        name: default
        func: commandFormatter
        args:
        - /usr/bin/pygmentize
        - "-f"
        - html
        - "-l"
        - "%LANG%"
        - "-O"
        - "nowrap=True,encoding=utf-8"
      text:
        name: text
        func: plainText
      markdown:
        name: markdown
        func: markdown
      ansi:
        name: ansi
        func: commandFormatter
        args:
        - /usr/local/bin/ansi2html
        - "--naked"
      iphonesyslog:
  17. Next we'll need to build a CSS file which will give color to the pastes:
    pygmentize -f html -S $STYLE > public/css/theme-pygments.css

    You can choose from several styles/color themes:

    - monokai
    - manni
    - rrt
    - perldoc
    - borland
    - colorful
    - default
    - murphy
    - vs
    - trac
    - tango
    - fruity
    - autumn
    - bw
    - emacs
    - vim
    - pastie
    - friendly
    - native

    I used monokai:

    pygmentize -f html -S monokai > public/css/theme-pygments.css
  18. If all went well all that is left to do is to start the service:
    ./ghostbin
  19. Here's an screenshot of my install: Ghostbin Installation
  20. I would also recommend running the binary with the --help flag:
    $ ./ghostbin --help
    Usage of ./ghostbin:
    -addr string
        bind address and port (default "0.0.0.0:8080")
    -alsologtostderr
        log to standard error as well as files
    -log_backtrace_at value
        when logging hits line file:N, emit a stack trace
    -log_dir string
        If non-empty, write log files in this directory
    -logtostderr
        log to standard error instead of files
    -rebuild
        rebuild all templates for each request
    -root string
        path to generated file storage (default "./")
    -stderrthreshold value
        logs at or above this threshold go to stderr
    -v value
        log level for V logs
    -vmodule value
        comma-separated list of pattern=N settings for file-filtered logging

    This allows you to see flags you can run with the binary. I run mine as such:

    ./ghostbin -logtostderr

    This will just log the errors to the screen.

Setting Up GhostBin w/ Nginx

  1. Install Nginx:
    apt install nginx
  2. Create a Nginx configuration file for GhostBin:

    nano /etc/nginx/sites-available/ghostbin.conf
    # Upstream configuration
    upstream ghostbin_upstream {  
        server 0.0.0.0:8080;
        keepalive 64;
    }
    
    # Public
    server {  
        listen 80;
        server_name ghostbin.YOURDOMAIN.com; # domain of my site
    
        location / {
            proxy_http_version 1.1;
            proxy_set_header   X-Real-IP        $remote_addr;
            proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
            proxy_set_header   X-NginX-Proxy    true;
            proxy_set_header   Host             $http_host;
            proxy_set_header   Upgrade          $http_upgrade;
            proxy_redirect     off;
            proxy_pass         http://ghostbin_upstream;
        }
    }

    You'll obviously want to update the server_name bit. Save and exit the file.

  3. Next we need to make a symlink so Nginx knows to load the configuration:
    cd ../site-enabled
    ln -s ../sites-available/ghostbin.conf .
  4. Restart the Nginx service:
    systemctl restart nginx

    Your GhostBin site should now be available at http://ghostbin.YOURDOMAIN.com!

Notes

  • Whenever I start up the binary I see:

    E0815 21:19:58.915843   19895 main.go:773] Expirator Error: open expiry.gob: no such file or directory

    This doesn't appear to be an issue and I haven't had any issues with using GhostBin thus far. There seems to be some code in main.go referencing it. It looks related to the expiration of the paste, but I don't know GoLang so I can't be sure.

    pasteExpirator = gotimeout.NewExpirator(filepath.Join(arguments.root, "expiry.gob"), &ExpiringPasteStore{pasteStore})
  • It looks like the GhostBin repository has been renamed to 'spectre'. It looks like this was done to "de-brand" it for people who want to run it themselves and separate it from GhostBin.com where I believe the developer run their own copy. See this commit.
  • You should definitely set up your install with Let's Encrypt for SSL.
  • It seems like the binary was renamed back to ghostbin from spectre. Why? I don't know. I also noticed there is a binary in /home/ghostbin/go/bin/ but it doesn't seem to work? 🤷🏼‍♂️