Accessing Meteor Settings in a Self-Owned Production Environment - settings

According to Meteor's documentation, we can include a settings file through the command line to provide deployment-specific settings.
However, the --settings option seems to only be available through the run and deploy commands. If I am running my Meteor application on my own infrastructure - as outlined in the Running on Your Own Infrastructure section of the documentation - there doesn't seem to be a way to specify a deployment-specific settings file anywhere in the process.
Is there a way to access Meteor settings in a production environment, running on my own infrastructure?

Yes, include the settings contents in an environmental variable METEOR_SETTINGS. For example,
export METEOR_SETTINGS='{"privateKey":"MY_KEY", "public":{"publicKey":"MY_PUBLIC_KEY", "anotherPublicKey":"MORE_KEY"}}'
And then run the meteor app as normal.
This will populate the Meteor.settings object has normal. For the settings above,
Meteor.settings.privateKey == "MY_KEY" #Only on server
Meteor.settings.public.publicKey == "MY_PUBLIC_KEY" #Server and client
Meteor.settings.public.anotherPublicKey == "MORE_KEY" #Server and client
For our project, we use an upstart script and include it there (although upstart has a slightly different syntax). However, if you are starting it with a normal shell script, you just need to include that export statement before your node command. You could, for example, have a script like:
export METEOR_SETTINGS='{"stuff":"real"}'
node /path/to/bundle/main.js
or
METEOR_SETTINGS='{"stuff":"real"}' node /path/to/bundle/main.js
You can find more information about bash variables here.

Related

How to enable NetBeans 15 for Mac honour the system environment variables with Gradle builds

I have recently started to use GitHub Packages to distribute our shared libraries internally and have retrospectively changed the Gradle build configuration to use credentials based on system environment variables, rather than hard-coded e.g.
repositories {
mavenLocal() // only use when testing -SNAPSHOT locally
mavenCentral() // third-parties
maven { // our-library
name = "MyLibrary"
url = "https://maven.pkg.github.com/MyCompany/mylibrary"
credentials {
username = project.findProperty("git_username") ?: System.getenv("git_username")
password = project.findProperty("git_token") ?: System.getenv("git_token")
}
}
}
Unfortunately no matter how many environment variables I changed, whether in ~/.zshrc or .zshenv or .bash_profile or /etc/launchd.conf the build was indicating that the credentials were prohibited, or more accurately were resolved as nul.
Each time I changed a config I also ran the appropriate source to ensure it was active, I even resorted to rebooting, just in case.
The environment variable would always show in the terminal confirming the environment variable was always set up correctly, e.g. echo $git_username or printenv yielded the environment variable and expected sensitive token.
After a lot of experimenting and with the help of a colleague we determined that launching NetBeans 15 from the dock wasn't helping, so instead we also added the following line to ~/.zshrc
alias netbeans="/Applications/NetBeans/Apache\ NetBeans\ 15.app/Contents/MacOS/netbeans &"
But now to launch NetBeans I can't use the dock icon, but manually launch the terminal and then type
netbeans
Here's the new lines added to ~/.zshrc
#
# RW - For GitHub Package access
#
export git_username=NotApplicableUsesToken
export git_token=redacted1
export git_publish_username=NotApplicableUsesToken
export git_publish_token=redacted2
#
# RW - So Netbeans launches and honours the environment variables above
#
alias netbeans="/Applications/NetBeans/Apache\ NetBeans\ 15.app/Contents/MacOS/netbeans &"
My question is, why didn't NetBeans when launched from the dock discover the environment variables? How should I configure NetBeans to pickup the environment variables without this workaround?
The Aqua GUI doesn't read any of the shell configuration files, e.g. .bash_profile, .bashrc, .login, .profile, .zprofile, or .zshrc. You were correct to start looking at launchd. Unfortunately /etc/launchd.conf is no longer supported and the file is not read.
Apple's Runtime Configuration Guidelines in the Environment Variables section states:
There are two ways to make environment variables available to an application. The first is to define the variables in a Terminal session and then launch the application from the same session. ...
The second way to associate environment variables with an application is to include the LSEnvironment key in the application’s information property list file. ...
Editing an application's plist doesn't seem like the best idea and your changes may be lost when the application is updated.
There is a third approach.
launchctl has setenv, unsetenv, and getenv sub-commands for managing environment variables. However the environment variables are not persisted across launchd instances.
It seems that a common approach is to create an agent job .plist in ~/Library/LaunchAgents that runs at user login to macOS that will execute launchctl setenv to set the environment variables that should be available to applications launched from the dock. There are discussions at "Set systemwide variable with /etc/launchd.conf does not work in 10.10" and "Environment variables for GUI apps" that point to resources for this approach. You may also want to see Creating Launch Daemons and Agents.
I haven't tested or tried this approach myself.

What is a foolproof way to make environment variables available to a script?

I have this script on an Ubuntu VM that uses an environment variable that is set in a script in /etc/profile.d/appsetup.sh.
The variable is used in my script, server-up.sh, to start my Java app:
export path=$KEYSTORE_PATH
java -jar -Dsecurity.keystore.path=$path [jarfile]
If I echo the variable, it works:
$ echo $KEYSTORE_PATH
/etc/ssl/certs
And if I run the script on my own (sudo sh server-up.sh) it runs and uses the environment variable just fine.
However, when the script is executed from Jenkins' "Execute Shell" step (on the same VM), it apparently can't access the environment variable, even though supposedly it's available system-wide.
I've tried setting the owner of server-up.sh to both root and jenkins and Jenkins runs it either way, but in neither case does it get the environment variables. In Jenkins, I also tried using the command sudo -E /[path]/server-up.sh but then the job fails and an error says sudo: sorry, you are not allowed to preserve the environment.
I've googled a dozen times for various things, but almost everything that comes up is people asking how to set environment variables in Jenkins, and I don't need to do that; I just want a script that Jenkins can execute have access to system environment variables.
What do I need to do to get this working?
Make a small change to allow the /etc/profile.d/appsetup.sh script to output the variable to a file, where the Jenkins job can access this variable to create an environment variable available for your job to run successfully.
I don't think the context and needs are explained sufficiently well to properly answer the question with a here's how you do it.
On a server, jenkins.war launches from a shell (or a root shell which invokes a shell script with commands which launches jenkins), which has an environment and to which you can set and pass parameters. Those exist in the context of the jenkins.war process. If you run from a daemon (initd / systemd) you get a non-in=teractive shell, which is set differently to your normal shell.
Your Jenkins will typically have Nodes launching agents on remote servers. Those are typically launched via a non-interactive shell (so no user .profile settings).
Then the jobs themselves run on one of the agents where the executor launches a shell for the job execution. Sub-shells may be launched for specific steps.
The two context you mention sudo sh server-up.sh and Jenkins' "Execute Shell" step (on the same VM), even on the same VM do not inherit the same environment as the Node is launched on it's own process using a non-interactive shell and is not aware of anything in your server-up.sh script; it (generally) just gets the /etc/profile.
You have options. You can set Global variables within Jenkins: ${JENKINS_URL}/configure
Global Properties
[ X ] Environment variables
[ X ] Prepare jobs environment (requires Env Inject plugin)
The same options also exist at the Node level
You can install the slaves-setup plugin, which allows you some customization when launching agents (aka slaves).
You can install the Environment Injector plugin, which adds the previously mentioned Prepare jobs environment feature.
It also adds jobs specific configuration options for:
[ X ] Prepare an environment for the run
Plus under the Build Environment section,
[ X ] Inject environment variables to the build process
and
[ X ] Inject passwords to the build as environment variables
Those are encrypted, and I believe are masked
Finally, you can add a build step to Inject environment variables, useful if you need to have different values for different steps.
BUT it's certs in a keystore!
Given that you also mention what you are trying to make available is $KEYSTORE_PATH=/etc/ssl/certs, I wonder if you've explored using the Credentials plugin? Is supports a wide variety of credential types, including:
Password
Username and password
SSH private key
Public Certificate and private key
Binary blob data
That OAuth thingy
The obvious benefit to using this approach vs cooking your own is it's been designed to work securely with Jenkins so your secrets don't get inadvertently exposed. Aside from the extensive documentation on the plugin site, there's more in the book on Using credentials, using them in a pipeline which also mentions the Snippet generator will stub it for you, and on the Cloudbees site - Injecting secrets into builds. You can probably find plenty of help here in S/O and DevOps.
You may also wish to explore the newly introduced Git credentials binding for sh, bat, and powershell, though not sure that's applicable in your case.

spring-boot launch-script: how to avoid pid_folder identity-subdirectory?

We are using spring-boot with the embedded launcher-script in service mode, to have daemonized/init.d behavior.
We however do not have an /etc/init.d symlink to the spring-boot jar as that would require using sudo. we avoid sudo to pass a profile-environmental like -Dspring.profiles.active=$APP_PROFILE in the JAVA_OPTS
(this won't work when started via sudo but defined in /home/appuser/.bashrc (?) )
We have this directory-layout with some indirections. basically app.jar => current/app.jar => build-xx/app.jar
appuser#host:~/apps/services$ ls
app.jar -> /home/appuser/apps/services/current/services-1.0-SNAPSHOT.jar
current -> /home/appuser/apps/services/services-1298
services-1298
When starting the application with app.jar start the launch-script generates an additional pid-subdirectory in the pid-folder based on the "identity" of the program. For us this can look like this:
/home/appuser/apps/services/run/services-1.0-SNAPSHOT_homeappuserappsservicesservices-1298/services.pid
Unlike when used with an symlinked /etc/init.d which gets special treatment and the pid-subdir services-1.0-SNAPSHOT_homeappuserappsservicesservices-1298 is omitted/stays stable.
This dynamic pid-subdir makes it very hard for us to check the daemon's status or start/stop during deployment because you have to always get the sequence right and nobody is stopping you from starting a process twice (the old instance and now a new instance with a new identity-subdir).
So, does anyone know why this pid-subdir-identity stuff must exist and what would be our best way to deal with it?
Do we have a bad setup?
Any advice appreciated.
You can control the identity by using the APP_NAME environment variable.
I'd recommend configuring your service's environment variables using a .conf file next to the jar file. For example, if your app is called app.jar, you conf file should be named app.conf and be placed in the same directory as the jar. You can then configure APP_NAME and JAVA_OPTS etc for your application. This should allow you to use init.d if you so wish.

Set global environment variables inside Xcode build phase run script

I'm using Jenkins to do continuous integration builds. I have quite a few jobs that have much of the same configuration code. I'm in the midst of pulling this all out into a common script file that I'd like to run pre and post build.
I've been unable to figure out how to set some environment variables within that script, so that both the Xcode build command, and the Jenkins build can see them.
Does anyone know if this is possible?
It is not possible to do exactly what you ask. A process cannot change the environment variables of another process. The pre and post and actual build steps run in different processes.
But you can create a script that sets the common environment variables and share that script between all your builds.
The would first call your shell to execute the commands in the script and then call xcodebuild:
# Note the dot in the beginning of the next line. It is not a typo.
. set_environment.sh
xcodebuild myawesomeapp.xcodeproj
The script could look like this:
export VARIABLE1=value1
export VARIABLE2=value2
How exactly your jobs will share the script depends on your environment and use case. You can
place the script in some well-known location on the Jenkins host or
place the script in the version controlled source tree if all your jobs share the same repository or
place the script in a repository of its own and make a Jenkins build which archives the script as a build artifact. All the other jobs would then use Copy Artifact plugin to get a copy of the script from the artifacts of script job.
From Apple's Technical Q&A QA1067 it appears that if you create the file /Users/YOU/.MacOSX/environment.plist and populate it with your desired environment variables that all processes (launched by the user with the environment.plist file in their home dir) will pick up these environment variables. You may need to restart your computer (or just log out and back in) before a newly launched process will pick up the variables.
This article also claims that Xcode will also pass these variables to a build phase script. I have not tested it yet but next time I restart my MacBook I will let you know if it worked.
From http://developer.apple.com/library/mac/#/legacy/mac/library/qa/qa1067/_index.html
Q: How do I set environment for all processes launched by a specific
user?
A: It is actually a fairly simple process to set environment variables
for processes launched by a specific user.
There is a special environment file which loginwindow searches for
each time a user logs in. The environment file is:
~/.MacOSX/environment.plist (be careful it's case sensitive). Where
'~' is the home directory of the user we are interested in. You will
have to create the .MacOSX directory yourself using terminal (by
typing mkdir .MacOSX). You will also have to create the environment
file yourself. The environment file is actually in XML/plist format
(make sure to add the .plist extension to the end of the filename or
this won't work).

Set an environment variable in a Sinatra app?

I want to set MONGOHQ_URL in my sinatra app in order to be able to do this:
uri = URI.parse(ENV['MONGOHQ_URL'])
How do I setup the MONGOHQ_URL?
on Windows: set MONGOHQ_URL=test
on Unix (bash): export MONGOHQ_URL=test
on Unix (csh): setenv MONGOHQ_URL test
In order for your environment variables to always be available to your app, you will need to make sure they get exported whenever a new terminal session launches. It's common to put these in .bashrc for example
export MONGOHQ_URL=https://some.long.secure.url # for example
But for your local development purposes you might want to check out dotenv gem which allows you to store local environment variables in .env file in root of your project. For production, you should be able to Figaro with Sinatra, for more see answer to this question or see readme on the github repo
In general you should always make sure not to commit sensitive config information in your codebase so make sure to add any files like .env or config/application.yml to your .gitignore file.

Resources