StackScripts API

So recently I've gotten spoiled with other cloud provider meta data services. The kind of API where I can hit an 'internal' URL like 169.254.169.254/latest/user-data/ and pull out usernames, passwords, SSH-keys etc as I deploy new instances. I can't seem to find such a service on Linode so I'm hoping to use the StackScripts API instead.

When I create a StackScript and 'deploy an image' using one, what technically is occuring? Is linode stuffing a shell script into a 'standard' image that gets executed on first boot? If so what is the path that it does so? Is it different per supported distribution? Does Linode at some point try to delete that shell script?

Since I run a fully custom and encrypted distribution via pv-grub what I would like to do is deploy a 'standard' image with said StackScript and then simply mount that drive in my custom distribution and slurp out the StackScript that I can dynamically push via the Linode API at deploy time. That way I can fully customize my own instances dynamically. Anyone done any such machinations?

What other solutions have you come up to deploy SSH-keys and such? I could come up with my own external service but I'm concerned I would implement some gaping security hole that would be easily exploitable.

Sie suchen eine SEO Firma, SEO Experten, SEO Beratung, SEO Agentur oder allgemein Informationen rund um die Thematik Suchmaschinenoptimierung (SEO)? Lesen Sie kostenlos den SEO-Blog und treffen Sie die richtige Wahl für die passende SEO Agentur!

1 Reply

StackScripts work by taking the distro image you pick (from the list of Linode's standard images) and injecting the script you give it, with the variables you set when you create the image from stackscript (https://www.linode.com/api/linode/linod … tackscript">https://www.linode.com/api/linode/linode.disk.createfromstackscript StackScriptUDFResponses / https://www.linode.com/docs/platform/st … s-and-udfs">https://www.linode.com/docs/platform/stackscripts#variables-and-udfs ). Note that you can set rootSSHkey with the API when deploying an image, whether from StackScripts, a stock image, or Linode Images (https://www.linode.com/docs/platform/linode-images).

The StackScript gets dropped in /root/StackScript (if I remember correctly), and Linode moves your distribution's getty binary (/usr/bin/agetty, for example) to another location and replaces it with a short script that runs /root/StackScript, then replaces the getty file with the saved original getty binary and exits. That means that the StackScript runs on /dev/ttyS0 (or /dev/hvc0 on Xen) on first-boot, when your system thinks it's starting the Lish TTY (and as such you can watch the Stackscript run on Lish), and then once the script exits, the regular tty spawns there. This has a weird quirk: your stackscript needs to exit cleanly, so that the cleanup takes place. Examples of not doing that: rebooting inside a stackscript, which causes it not to exit, and the stackscript will keep running on every boot since /usr/bin/agetty never gets fixed up. Ways around this include anything that pushes the reboot after the end of the script, like backgrounding it / nohupping it or adding it to cron and then exiting.

You can deploy an image from a stackscript and then rather than boot it, boot Rescue Mode and mount the disk image / look around to confirm the above. Since it's using the getty, the script runs at first regular boot, not at image creation time.

If you're looking for more flexibility in what you can inject into the build process, I might recommend a 2 phased approach, using Linode Images:

Step 1: Use the API to deploy a disk and config profile, either from a stackscript or just a stock image

Step 2: Boot the image

Step 3: Use fabric or ansible or really any other execution tool to set the image up as desired (things like setting up /boot/grub/menu.lst for pv-grub (weird note,in case you didn't know: with pv-grub, there's no requirement that you have grub installed or put it on the disk's MBR, just that you have /boot/grub/menu.lst (or grub.cfg for grub2) and the right kernel/initrd/etc files)

Step 4: Add an init script or similar so that the system configures itself from whatever config source you want (I generally inject a file at-first-boot of a newly provisioned system with SCP, but my systems are very non-standard)

Step 5: Shut down the Linode

Step 6: Imagize the image: https://www.linode.com/api/linode/linode.disk.imagize

Now, moving forward, you can use https://www.linode.com/api/linode/linod … efromimage">https://www.linode.com/api/linode/linode.disk.createfromimage to deploy this image as many times as you want. And at boot, it'll run the init script, do its own setup similar to what a stackscript would do, and make itself ready for use.

For a somewhat convoluted real-life example:

First I deploy from a stackscript, which puts my init script in place and makes sure packages are up to date, then imagizes the result: https://github.com/dock0/deploy_tool/bl … e-build.rb">https://github.com/dock0/deploy_tool/blob/master/meta/image-build.rb

The stackscript: https://github.com/dock0/deploy_tool/bl … tackscript">https://github.com/dock0/deploy_tool/blob/master/meta/stackscript

Now I have an image to deploy from. My system is a bit weird in that this image actually builds the desired system onto a separate disk entirely: https://github.com/dock0/deploy_tool/bl … /deploy.rb">https://github.com/dock0/deploy_tool/blob/master/meta/deploy.rb

So when I want a new system, I run ./deploy.rb, it uses the maker Image as a springboard to build out this new system on /dev/sdc, then updates the config so /dev/sdc is the root volume (which takes effect on the next reboot)

Then that uses https://github.com/dock0/deploy_tool/bl … nfigure.rb">https://github.com/dock0/deploy_tool/blob/master/meta/configure.rb to inject the per-system configuration onto the otherwise blank slate

Then the whole thing reboots, booting into the newly minted rootfs with its configuration, ready for use.

  • Les

Reply

Please enter an answer
Tips:

You can mention users to notify them: @username

You can use Markdown to format your question. For more examples see the Markdown Cheatsheet.

> I’m a blockquote.

I’m a blockquote.

[I'm a link] (https://www.google.com)

I'm a link

**I am bold** I am bold

*I am italicized* I am italicized

Community Code of Conduct