• Blog
  • Docs
  • Careers
  • Get Support
  • Contact Sales
DigitalOcean
  • Featured AI Products

    Compute

    Build, deploy, and scale cloud compute resources

    Containers and Images

    Safely store and manage containers and backups

    Managed Databases

    Fully managed resources running popular database engines

    Management and Dev Tools

    Control infrastructure and gather insights

    Networking

    Secure and control traffic to apps

    Security

    Help protect your account and resources with these security features

    Storage

    Store and access any amount of data reliably in the cloud

    Browse all products

  • AI/ML

    CMS

    Data and IoT

    Developer Tools

    Gaming and Media

    Hosting

    Security and Networking

    Startups and SMBs

    Web and App Platforms

    See all solutions

  • Community

    Documentation

    Developer Tools

    Get Involved

    Utilities and Help

  • Become a Partner

    Marketplace

  • Pricing
  • Log in
  • Sign up
  • Log in
  • Sign up

Company

  • About
  • Leadership
  • Blog
  • Careers
  • Customers
  • Partners
  • Referral Program
  • Affiliate Program
  • Press
  • Legal
  • Privacy Policy
  • Security
  • Investor Relations

Products

  • GPU Droplets
  • Bare Metal GPUs
  • Inference Engine
  • Data & Learning
  • Model Library
  • Droplets
  • Kubernetes
  • Functions
  • App Platform
  • Load Balancers
  • Managed Databases
  • Spaces
  • Block Storage
  • Network File Storage
  • API
  • Uptime
  • Cloud Security Posture Management (CSPM)
  • Identity and Access Management (IAM)
  • Cloudways
  • View all Products

Resources

  • Community Tutorials
  • Community Q&A
  • CSS-Tricks
  • Write for DOnations
  • Currents Research
  • DigitalOcean Startups
  • Wavemakers Program
  • Compass Council
  • Open Source
  • Newsletter Signup
  • Marketplace
  • Pricing
  • Pricing Calculator
  • Documentation
  • Release Notes
  • Code of Conduct
  • Shop Swag

Solutions

  • AI Training GPU
  • GPU Inference
  • VPS Hosting
  • Website Hosting
  • VPN
  • Docker Hosting
  • Node.js Hosting
  • Web Mobile Apps
  • WordPress Hosting
  • Virtual Machines
  • View all Solutions

Contact

  • Support
  • Sales
  • Report Abuse
  • System Status
  • Share your ideas

Company

  • About
  • Leadership
  • Blog
  • Careers
  • Customers
  • Partners
  • Referral Program
  • Affiliate Program
  • Press
  • Legal
  • Privacy Policy
  • Security
  • Investor Relations

Products

  • GPU Droplets
  • Bare Metal GPUs
  • Inference Engine
  • Data & Learning
  • Model Library
  • Droplets
  • Kubernetes
  • Functions
  • App Platform
  • Load Balancers
  • Managed Databases
  • Spaces
  • Block Storage
  • Network File Storage
  • API
  • Uptime
  • Cloud Security Posture Management (CSPM)
  • Identity and Access Management (IAM)
  • Cloudways
  • View all Products

Resources

  • Community Tutorials
  • Community Q&A
  • CSS-Tricks
  • Write for DOnations
  • Currents Research
  • DigitalOcean Startups
  • Wavemakers Program
  • Compass Council
  • Open Source
  • Newsletter Signup
  • Marketplace
  • Pricing
  • Pricing Calculator
  • Documentation
  • Release Notes
  • Code of Conduct
  • Shop Swag

Solutions

  • AI Training GPU
  • GPU Inference
  • VPS Hosting
  • Website Hosting
  • VPN
  • Docker Hosting
  • Node.js Hosting
  • Web Mobile Apps
  • WordPress Hosting
  • Virtual Machines
  • View all Solutions

Contact

  • Support
  • Sales
  • Report Abuse
  • System Status
  • Share your ideas
© 2026 DigitalOcean, LLC.Sitemap.
Product updates

Using Packer to Create a 1-Click NKN Image on DigitalOcean

author

By Yilun Zhang, NKN

  • Published: March 7, 2019
  • 8 min read
<- Back to blog home

NKN is the new kind of P2P network connectivity protocol and ecosystem powered by a novel public blockchain. Our open source node software allows internet users to share network connections and unused bandwidth for rewards. By running an NKN node, you become part of the NKN network community helping to build the decentralized internet so everyone can enjoy secure, low cost, and universally accessible connectivity.

Recently NKN’s Testnet has grown to over 6,000 community full nodes and many of these nodes are running on DigitalOcean. In fact, one of the most frequently asked questions from our community is how to set up a NKN full node on DigitalOcean? We have a few tutorials on how to do that; however, having to properly and safely set up the Droplet environment creates significant friction for those who have just heard of the project and want to try it for themselves, preferably in just a few minutes.

Luckily for all, DigitalOcean now provides a Marketplace where we can release a 1-Click App for NKN, a very convenient and user-friendly way to deploy preconfigured droplets in 60 seconds. You can quickly start a NKN 1-Click App from the “Marketplace” in your DigitalOcean cloud control panel, or by visiting DigitalOcean Marketplace directly.

Using Packer to Create a 1-Click Image

To make the NKN 1-Click App in DigitalOcean’s new Marketplace, we recognized that creating a preconfigured production-ready image takes effort: not just to create the initial image, but every time that image needs to be updated. A few repetitive but necessary steps need to be done every time a snapshot is created, e.g. starting and stopping Droplets, removing user history and trace, creating a snapshot from Droplets. Doing these steps manually for each image update is not only time consuming, but can open the opportunity for mistakes.

Another headache comes when we want to create the same image for multiple cloud providers. Typically each cloud providers has their own steps and requirements when creating an image. For example, DigitalOcean requires an image to have `cloud-init` set up, while Google Cloud requires an image to be licensed. These differences need to be taken into account every time an image is updated.

Since creating and maintaining an app image is repetitive and has a lot of detailed steps that easily break when doing them manually, we chose to handle the process using Packer, which can automate all these processes across many different cloud providers.

With Packer, you provide the configuration scripts and your API key for your cloud provider, and Packer will do the rest. The result is a ready-to-use image for each cloud provider. Most importantly, everything is automatic, which means it’s reproducible and can be part of continuous integration. Let’s dig a little bit deeper to see how to do it in detail.

There are quite a few ways to install Packer as you can see in the official documentation. The simplest way is to use the precompiled binary.

Obtaining a DigitalOcean API Token

To use Packer with DigitalOcean, we first need to obtain (or generate) a DigitalOcean API Token. This can be done on the DigitalOcean website:

Note that both read and write scope are needed for the API token.

DigitalOcean Packer Builder

A builder in Packer will create an image on a certain platform from some configuration, and DigitalOcean is one of the supported builders. A basic Packer example which creates a plain Ubuntu image on DigitalOcean is as simple as the following Packer template:

{ “builders”: [ { “type”: “digitalocean”, “api_token”: “Your DigitalOcean API Token”, “image”: “ubuntu-18-04-x64”, “region”: “nyc3”, “size”: “s-1vcpu-1gb”, “ssh_username”: “root” } ] }

If you save the above Packer template as packer.json, include your DigitalOcean API token and run packer build packer.json, you will get a working Ubuntu image in your DigitalOcean account in a couple minutes!

If we look at the template above, the image key specifies the basic OS image to use; the region and size are used for the temporary droplet packer creates (and will destroy automatically); and, the ssh_username key specifies which user Packer will use to ssh into the machine.

You probably noticed that builders in the Packer template are an array, so if we want to build the same image on multiple cloud providers, we just need to add builders into the array, and all of them will be built in parallel.

Packer supports quite a lot of builders. More information about Packer builder can be found here.

Provisioning the Image

The above basic example only gives you a standard Ubuntu image, which is probably not what you want. To build a custom image, we need provisioners that customize an image by installing and configuring software before taking the Snapshot and turning it into an image. Let’s add provisioners to the Packer template in the previous step:

{ “builders”: [ { “type”: “digitalocean”, “api_token”: “Your DigitalOcean API Token”, “image”: “ubuntu-18-04-x64”, “region”: “nyc3”, “size”: “s-1vcpu-1gb”, “ssh_username”: “root” } ], “provisioners”: [ { “type”: “shell”, “inline”: [ “sleep 30”, “sudo apt-get update”, “sudo apt-get install -y supervisor” ] }, { “type”: “shell”, “script”: “./scripts.sh” }, { “type”: “file”, “source”: “./nkn.conf”, “destination”: “/tmp/” }, { “type”: “shell”, “inline”: [ “sudo mv /tmp/nkn.conf /etc/supervisor/conf.d/” ] } ] }

We added quite a few provisioners to the Packer template, and they will be executed sequentially. Let’s look at them one by one.

The first provisioner is an inline shell type, which contains a few commands to run on the droplet before creating the image. Note that the first command sleep 30 makes sure the system is properly initialized before executing the rest of the command.

The second provisioner is a shell script type. It’s very similar to the first one but specifies a shell script file to run on the droplet.

The third provisioner uploads a local file to the droplet, and the fourth provisioner copies the uploaded file into the designated location. One can also upload it directly to the target location which works properly on DigitalOcean but not necessarily on other cloud platforms if ssh_username does not have the required permissions.

You can find more information about supported provisioners in the official documentation.

Passing Variables to the Packer Template

Currently, the Packer template contains your DigitalOcean API token in plain text, which is a very dangerous thing to do if you share it with other people. A much better way is to pass the API token as a variable to the template. Do this by modifying the Packer template (“provisioners” section does not need to be changed):

{ “variables”: { “do_api_token”: “” }, “builders”: [ { “type”: “digitalocean”, “api_token”: “{{user `do_api_token`}}”, “image”: “ubuntu-18-04-x64”, “region”: “nyc3”, “size”: “s-1vcpu-1gb”, “ssh_username”: “root” } ], “provisioners”: […] }

To build the image, use the command packer build -var ‘do_api_token=XXX’ packer.json where XXX should be replaced by your DigitalOcean API token. Using the variable is not only safer, but also makes it possible to create the same image in different DigitalOcean accounts with the same template.

A Few Final Tips

Here are some tips based on our experience in creating a multi-platform images using Packer:

  1. Updating an image is typically more complicated than updating the code, so it’s better to create your image such that it will fetch the latest version of your software when the Droplet is initiated such that the image itself does not need to be updated every time your software updates.
  2. For the same reason as above, it’s useful to have some sort of auto-update mechanism so that existing one-click users will not need to update or even re-create the Droplet manually.
  3. All Droplets created from the same image are nearly identical on DigitalOcean, so if you have any sort of “account” in your software, the credentials may need to be generated randomly and saved to disk so users can access it. In our case we also set the credential file permission so that only a certain user (plus superusers) can view the content of the file.

Do not assume ssh_username is a superuser like root. Although we use root user on DigitalOcean, other platforms may have different user settings, and provisioners may not work properly due to lack of permissions.

Complete Code

The complete config we used to create 1-click image on DigitalOcean and other platforms can be found at GitHub.

Yilun Zhang is co-founder and CTO of NKN.org.

About the author

Yilun Zhang, NKN
Yilun Zhang, NKN
Author

Share

  • Product Updates

Start building today

From GPU-powered inference and Kubernetes to managed databases and storage, get everything you need to build, scale, and deploy intelligent applications.
Sign up

Related Articles

Run Codex in the cloud – DigitalOcean for Codex is now available
Product updates

Run Codex in the cloud – DigitalOcean for Codex is now available

Ari Sigal
  • June 25, 2026
  • 3 min read

Read more

Server-Side Tools Are Now Available for DigitalOcean Inference Engine
Product updates

Server-Side Tools Are Now Available for DigitalOcean Inference Engine

Grace Morgan
  • June 17, 2026
  • 3 min read

Read more

Model Evaluations: Prove Your Routing Policy Actually Works
Product updates

Model Evaluations: Prove Your Routing Policy Actually Works

Sathish Jothikumar

  • June 4, 2026
  • 7 min read

Read more