diff --git a/doc/cli.markdown b/doc/cli.markdown
index 214f6d4c..3034e1d2 100644
--- a/doc/cli.markdown
+++ b/doc/cli.markdown
@@ -1478,6 +1478,7 @@ Examples:
 	$ balena push 10.0.0.1
 	$ balena push 10.0.0.1 --source <source directory>
 	$ balena push 10.0.0.1 --service my-service
+	$ balena push 10.0.0.1 --env MY_ENV_VAR=value --env my-service:SERVICE_VAR=value
 
 	$ balena push 23c73a1.local --system
 	$ balena push 23c73a1.local --system --service my-service
@@ -1529,6 +1530,16 @@ Only valid when pushing to a local mode device.
 Only show system logs. This can be used in combination with --service.
 Only valid when pushing to a local mode device.
 
+#### --env &#60;env&#62;
+
+When performing a push to device, run the built containers with environment
+variables provided with this argument. Environment variables can be applied
+to individual services by adding their service name before the argument,
+separated by a colon, e.g:
+	--env main:MY_ENV=value
+Note that if the service name cannot be found in the composition, the entire
+left hand side of the = character will be treated as the variable name.
+
 # Settings
 
 ## settings
diff --git a/lib/actions/push.ts b/lib/actions/push.ts
index 7df75563..593148be 100644
--- a/lib/actions/push.ts
+++ b/lib/actions/push.ts
@@ -1,5 +1,5 @@
 /*
-Copyright 2016-2018 Balena Ltd.
+Copyright 2016-2019 Balena Ltd.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -114,6 +114,7 @@ export const push: CommandDefinition<
 		detached: boolean;
 		service: string;
 		system: boolean;
+		env: string | string[];
 	}
 > = {
 	signature: 'push <applicationOrDevice>',
@@ -153,6 +154,7 @@ export const push: CommandDefinition<
 			$ balena push 10.0.0.1
 			$ balena push 10.0.0.1 --source <source directory>
 			$ balena push 10.0.0.1 --service my-service
+			$ balena push 10.0.0.1 --env MY_ENV_VAR=value --env my-service:SERVICE_VAR=value
 
 			$ balena push 23c73a1.local --system
 			$ balena push 23c73a1.local --system --service my-service
@@ -224,6 +226,19 @@ export const push: CommandDefinition<
 				Only valid when pushing to a local mode device.`,
 			boolean: true,
 		},
+		{
+			signature: 'env',
+			parameter: 'env',
+			description: stripIndent`
+				When performing a push to device, run the built containers with environment
+				variables provided with this argument. Environment variables can be applied
+				to individual services by adding their service name before the argument,
+				separated by a colon, e.g:
+					--env main:MY_ENV=value
+				Note that if the service name cannot be found in the composition, the entire
+				left hand side of the = character will be treated as the variable name.
+			`,
+		},
 	],
 	async action(params, options, done) {
 		const sdk = (await import('balena-sdk')).fromSharedOptions();
@@ -282,6 +297,11 @@ export const push: CommandDefinition<
 						'The --system flag is only valid when pushing to a local mode device.',
 					);
 				}
+				if (options.env) {
+					exitWithExpectedError(
+						'The --env flag is only valid when pushing to a local mode device.',
+					);
+				}
 
 				const app = appOrDevice;
 				await exitIfNotLoggedIn();
@@ -324,6 +344,10 @@ export const push: CommandDefinition<
 						detached: options.detached || false,
 						service: options.service,
 						system: options.system || false,
+						env:
+							typeof options.env === 'string'
+								? [options.env]
+								: options.env || [],
 					}),
 				)
 					.catch(BuildError, e => {
diff --git a/lib/utils/device/deploy.ts b/lib/utils/device/deploy.ts
index 3e28528a..7beec4b6 100644
--- a/lib/utils/device/deploy.ts
+++ b/lib/utils/device/deploy.ts
@@ -50,6 +50,11 @@ export interface DeviceDeployOptions {
 	detached: boolean;
 	service?: string;
 	system: boolean;
+	env: string[];
+}
+
+interface ParsedEnvironment {
+	[serviceName: string]: { [key: string]: string };
 }
 
 async function checkSource(source: string): Promise<boolean> {
@@ -57,6 +62,58 @@ async function checkSource(source: string): Promise<boolean> {
 	return (await fs.exists(source)) && (await fs.stat(source)).isDirectory();
 }
 
+async function environmentFromInput(
+	envs: string[],
+	serviceNames: string[],
+	logger: Logger,
+): Promise<ParsedEnvironment> {
+	const { exitWithExpectedError } = await import('../patterns');
+	// A normal environment variable regex, with an added part
+	// to find a colon followed servicename at the start
+	const varRegex = /^(?:([^\s:]+):)?([^\s]+?)=(.*)$/;
+
+	const ret: ParsedEnvironment = {};
+	// Propolulate the object with the servicenames, as it
+	// also means that we can do a fast lookup of whether a
+	// service exists
+	for (const service of serviceNames) {
+		ret[service] = {};
+	}
+
+	for (const env of envs) {
+		const maybeMatch = env.match(varRegex);
+		if (maybeMatch == null) {
+			exitWithExpectedError(`Unable to parse environment variable: ${env}`);
+		}
+		const match = maybeMatch!;
+		let service: string | undefined;
+		if (match[1]) {
+			// This is for a service, we check that it actually
+			// exists
+			if (!(match[1] in ret)) {
+				logger.logDebug(
+					`Warning: Cannot find a service with name ${
+						match[1]
+					}. Treating the string as part of the environment variable name.`,
+				);
+				match[2] = `${match[1]}:${match[2]}`;
+			} else {
+				service = match[1];
+			}
+		}
+
+		if (service != null) {
+			ret[service][match[2]] = match[3];
+		} else {
+			for (const serviceName of serviceNames) {
+				ret[serviceName][match[2]] = match[3];
+			}
+		}
+	}
+
+	return ret;
+}
+
 export async function deployToDevice(opts: DeviceDeployOptions): Promise<void> {
 	const { loadProject, tarDirectory } = await import('../compose');
 	const { exitWithExpectedError } = await import('../patterns');
@@ -136,6 +193,12 @@ export async function deployToDevice(opts: DeviceDeployOptions): Promise<void> {
 		buildLogs,
 	);
 
+	const envs = await environmentFromInput(
+		opts.env,
+		Object.getOwnPropertyNames(project.composition.services),
+		globalLogger,
+	);
+
 	globalLogger.logDebug('Setting device state...');
 	// Now set the target state on the device
 
@@ -144,6 +207,7 @@ export async function deployToDevice(opts: DeviceDeployOptions): Promise<void> {
 	const targetState = generateTargetState(
 		currentTargetState,
 		project.composition,
+		envs,
 	);
 	globalLogger.logDebug(`Sending target state: ${JSON.stringify(targetState)}`);
 
@@ -376,6 +440,7 @@ function generateImageName(serviceName: string): string {
 export function generateTargetState(
 	currentTargetState: any,
 	composition: Composition,
+	env: ParsedEnvironment,
 ): any {
 	const services: { [serviceId: string]: any } = {};
 	let idx = 1;
@@ -390,6 +455,8 @@ export function generateTargetState(
 			labels: {},
 		};
 
+		opts.environment = _.merge(opts.environment, env[name]);
+
 		services[idx] = _.merge(defaults, opts, {
 			imageId: idx,
 			serviceName: name,
diff --git a/lib/utils/device/live.ts b/lib/utils/device/live.ts
index fe2790cd..e17b003c 100644
--- a/lib/utils/device/live.ts
+++ b/lib/utils/device/live.ts
@@ -348,7 +348,7 @@ export class LivepushManager {
 			// we rebuilt
 			const comp = _.cloneDeep(this.composition);
 			delete comp.services[serviceName];
-			const intermediateState = generateTargetState(currentState, comp);
+			const intermediateState = generateTargetState(currentState, comp, {});
 			await this.api.setTargetState(intermediateState);
 
 			// Now we wait for the device state to settle
@@ -356,7 +356,7 @@ export class LivepushManager {
 
 			// And re-set the target state
 			await this.api.setTargetState(
-				generateTargetState(currentState, this.composition),
+				generateTargetState(currentState, this.composition, {}),
 			);
 
 			await this.awaitDeviceStateSettle();