Move jar and associated files to a writable folder inside the snap so it can update itself and fetch other files

Hi! I’m trying to bundle XMage into a snap along with JRE, which I’ve done.

But, what I need some direction with is the following:

When you run the snap, the XMage launcher wants to update itself/install a bundled java package that the main app uses, and needs to be able to write to disk.

Furthermore, when you start the XMage client after update and login, you’ll have to download icons and MTG cards, and that need to be saved in a writable userspace.

So, I know $SNAP_USER_DATA and $HOME is writable, but I would want to know what the best practice would be to have the client reside inside user directory with a write permissions, and also how to define it for the java app inside the snapcraft.yaml, and if I would have to use hooks or not.

I’ve been looking into forum posts about the topic, but haven’t found anything that I might be able to replicate to my purpose (Because of my lack of knowledge on this subject, for I’ve never created a snap before).

I hope you guys can guide me with this.

Thanks!

I have an idea about mv/cp the java app to $SNAP_USER_DATA and point the jre, but not sure how to do the mv/cp properly.

So, I’ve set up snap/hooks with the file install:

#! /bin/sh

# Check if required files exist in $SNAP
if [ -f "$SNAP/XMageLauncher-0.3.8.jar" ]; then
  # Copy the files from the snap to the writable dir
  cp -rfa "$SNAP/*" "$SNAP_USER_DATA/"
fi

cp from $SNAP is futile, and I’m looking into the hierarchy of the build to locate the files location after "snapcraft prime --shell"

Also, wondering if I should be using override-build: rather than the install hook, or something else, and also if I need to call the install hook specifically in the snapcraft.yaml file.

that wont work the way you expect, the hooks are run at install time by snapd, so you are not executing it as a user and $SNAP_USER_DATA does not point anywhere.

If you actually want to copy anything into the users home, you’d have to do it by a command-chain wrapper …

but I doubt this is the right approach anyway, have you looked at environment variables or options to java itself, to simply make it use a different workdir ?

i.e. i know many java apps do set something like:

-Duser.home=$SNAP_USER_DATA

… and this is often sufficient

hey @ogra

yeah, I figured as much after I tried a few different things. I will look into the env variables.

the problem I have now is that my start script isn’t getting installed on build with snapcraft anymore… don’t know why, but it started after I did a cleanup and reverted the code (without changing the start script, the snapcraft.yaml declaration, nor the location of it )

thanks!

ok, so after I ran snapcraft clean and then backed up and removed the snap directory, ran snapcraft init again and then copied the backed up snapcraft.yaml file back into the snap dir, I got the paths to work again.

guess it got messed up after all this builds somehow.

the -Duser.home directive did not work as I hoped, for it still says Read-only file system upon update:

Error: =>[SwingWorker-pool-1-thread-2] DownloadTask.download java.io.FileNotFoundException: /snap/xmage-snap/x1/xmage.dl (Read-only file system)

well, I got everything to work with layout, env and install hooks… sort of…

here is the dev code: https://github.com/eddinn/xmage-snap/tree/dev

now when I run the xmage-snap, it gives me Error: =>[AWT-EventQueue-0] Config.saveProperties java.io.FileNotFoundException: /var/snap/xmage-snap/common/opt/xmage/installed.properties (Permission denied).

if I run sudo xmage-snap then everything works.

I have tried to add chown and chmod in the install hook, but that makes no difference.

does this have anything to do with when I install the snap in dev mode with the --dangerous flag, and will be resolved permission wise, after I change it to strict/stable, or do I need to do something else?

@ogra maybe you can shed some light on this and guide me in the right direction?

you are copying stuff to $SNAP_COMMON it seems … this points to /var/snap/<snapname>/common… /var and dirs underneath it are root owned and not writable by normal users, this is why you need sudo …

note that $SNAP_COMMON and $SNAP_DATA are typically used by services (running as root), not by normal applications … enduser apps would use $SNAP_USER_COMMON/_DATA but this is not accessible from the install hook, you’d need a command-chain wrapper that handles the copying at runtime/initial-startup on a per-user basis

@ogra gotcha! I will look into this. I know you have a lot on your plate with us novice users here, so thank you so much for your time and input you give.

IMHO the proper way to do this is to either:

  • Bundle everything the application needs to the snap and disable the self-update logic completely, ship the application update within the snap update instead.

    As application distributions, we don’t normally allow the application to update itself, as it may break if the dependency(e.g. Java runtime) requirement changes.

  • Bundle only the Java runtime and install the application on launch into a writable location, this reduces the snap size by avoiding shipping the application assets completely, however, it makes internet access required at launch time and also doesn’t prevent the aforementioned dependency-breaking problem.

1 Like

yeah, I could run the application, update it and get the java engine that it bundles with itself, and then pack everything. but I still would need to be able to let the end-user download/update his deck cards, game icons and save decks/configs.

the application updates are not frequent, but are required upon every new set/pack/card release, along with all card bannings and rule updates from Wizards of the Coast.

XMage is an free client that allows people to play Magic the Gathering and is completely developed by people who donate their time and skillset, and you can readily install it on linux, but I figured I’d learn myself to create a snap by bundling this in a snap to have people easily install and play MTG with XMage.

that’s proving to be more difficult and restricting than I was anticipating, and the documentation is not so much forthcoming in explaining some aspects of how things work, and it seems that with every problem that I solve, there are two more that stick their heads up…

That’s unfortunate however the same obstacles occur to all containerized software distributions, it would be less difficult if the upstream application supports customizing parts of their resource loading paths via configuration files/environment variables so you can redirect to directories writable by the running user, if not, custom patching may be required.

the documentation is not so much forthcoming in explaining some aspects of how things work

Please elaborate on what the docs are lacking and we’ll try to fix them(or by yourself, since all wiki pages are editable by the forum users).

I’d suggest reading the following articles if you haven’t as it provides basic info about the runtime environment of the snapped application:

1 Like