diff --git a/services/webapp/code/rosetta/core_app/computing_managers.py b/services/webapp/code/rosetta/core_app/computing_managers.py
index f065b319329d016474e0d0ff75915ac22019b6c2..4889817483fe89d874ae35c0c683a5bc132a4d71 100644
--- a/services/webapp/code/rosetta/core_app/computing_managers.py
+++ b/services/webapp/code/rosetta/core_app/computing_managers.py
@@ -1,5 +1,5 @@
 from .models import TaskStatuses, KeyPair, Task, Storage
-from .utils import os_shell, get_ssh_access_mode_credentials
+from .utils import os_shell, get_ssh_access_mode_credentials, sanitize_container_env_vars
 from .exceptions import ErrorMessage, ConsistencyException
 from django.conf import settings
 
@@ -107,6 +107,15 @@ class InternalStandaloneComputingManager(StandaloneComputingManager):
         if not task.requires_proxy and task.password:
             run_command += ' -eAUTH_PASS={} '.format(task.password)
 
+        # Env vars if any
+        if task.container.env_vars:
+            
+            # Sanitize again just in case the DB got somehow compromised:
+            env_vars = sanitize_container_env_vars(task.container.env_vars)
+            
+            for env_var in env_vars:
+                run_command += ' -e{}={} '.format(env_var, env_vars[env_var])
+
         # User data volume
         #run_command += ' -v {}/user-{}:/data'.format(settings.LOCAL_USER_DATA_DIR, task.user.id)
 
@@ -204,8 +213,19 @@ class SSHStandaloneComputingManager(StandaloneComputingManager, SSHComputingMana
             # Set pass if any
             authstring = ''
             if not task.requires_proxy_auth and task.password:
-                authstring = ' export SINGULARITYENV_AUTH_PASS={} && '.format(task.password)
+                authstring = ' && export SINGULARITYENV_AUTH_PASS={} '.format(task.password)
+
+            # Env vars if any
+            if task.container.env_vars:
+                varsstring = ''
+                # Sanitize again just in case the DB got somehow compromised:
+                env_vars = sanitize_container_env_vars(task.container.env_vars)
                 
+                for env_var in env_vars:
+                    varsstring += ' && export SINGULARITYENV_{}={} '.format(env_var, env_vars[env_var])
+            else:
+                varsstring = ''
+                    
             # Handle storages (binds)
             binds = ''
             storages = Storage.objects.filter(computing=self.computing)
@@ -241,7 +261,7 @@ class SSHStandaloneComputingManager(StandaloneComputingManager, SSHComputingMana
             run_command  = 'ssh -o LogLevel=ERROR -i {} -4 -o StrictHostKeyChecking=no {}@{} '.format(computing_keys.private_key_file, computing_user, computing_host)
             run_command += '/bin/bash -c \'"rm -rf /tmp/{}_data && mkdir -p /tmp/{}_data/tmp && mkdir -p /tmp/{}_data/home && chmod 700 /tmp/{}_data && '.format(task.uuid, task.uuid, task.uuid, task.uuid) 
             run_command += 'wget {}/api/v1/base/agent/?task_uuid={} -O /tmp/{}_data/agent.py &> /dev/null && export BASE_PORT=\$(python /tmp/{}_data/agent.py 2> /tmp/{}_data/task.log) && '.format(webapp_conn_string, task.uuid, task.uuid, task.uuid, task.uuid)
-            run_command += 'export SINGULARITY_NOHTTPS=true && export SINGULARITYENV_BASE_PORT=\$BASE_PORT && {} '.format(authstring)
+            run_command += 'export SINGULARITY_NOHTTPS=true && export SINGULARITYENV_BASE_PORT=\$BASE_PORT {} {} &&'.format(authstring, varsstring)
             run_command += 'exec nohup singularity run {} --pid --writable-tmpfs --no-home --home=/home/metauser --workdir /tmp/{}_data/tmp -B/tmp/{}_data/home:/home --containall --cleanenv '.format(binds, task.uuid, task.uuid)
             
             # Container part
@@ -254,7 +274,18 @@ class SSHStandaloneComputingManager(StandaloneComputingManager, SSHComputingMana
             authstring = ''
             if not task.requires_proxy_auth and task.password:
                 authstring = ' -e AUTH_PASS={} '.format(task.password)
+
+            # Env vars if any
+            if task.container.env_vars:
+                varsstring = ''
+                # Sanitize again just in case the DB got somehow compromised:
+                env_vars = sanitize_container_env_vars(task.container.env_vars)
                 
+                for env_var in env_vars:
+                    varsstring += ' -e {}={} '.format(env_var, env_vars[env_var])
+            else:
+                varsstring = ''
+         
             # Handle storages (binds)
             binds = ''
             storages = Storage.objects.filter(computing=self.computing)
@@ -293,7 +324,7 @@ class SSHStandaloneComputingManager(StandaloneComputingManager, SSHComputingMana
             run_command  = 'ssh -o LogLevel=ERROR -i {} -4 -o StrictHostKeyChecking=no {}@{} '.format(computing_keys.private_key_file, computing_user, computing_host)
             run_command += '/bin/bash -c \'"rm -rf /tmp/{}_data && mkdir /tmp/{}_data && chmod 700 /tmp/{}_data && '.format(task.uuid, task.uuid, task.uuid) 
             run_command += 'wget {}/api/v1/base/agent/?task_uuid={} -O /tmp/{}_data/agent.py &> /dev/null && export TASK_PORT=\$(python /tmp/{}_data/agent.py 2> /tmp/{}_data/task.log) && '.format(webapp_conn_string, task.uuid, task.uuid, task.uuid, task.uuid)
-            run_command += '{} {} run -p \$TASK_PORT:{} {} {} '.format(prefix, container_engine, task.container.interface_port, authstring, binds)        
+            run_command += '{} {} run -p \$TASK_PORT:{} {} {} {} '.format(prefix, container_engine, task.container.interface_port, authstring, varsstring, binds)        
             if container_engine == 'podman':
                 run_command += '--network=private --uts=private '
             #run_command += '-d -t {}/{}:{}'.format(task.container.registry, task.container.image_name, task.container.image_tag)
@@ -435,8 +466,19 @@ class SlurmSSHClusterComputingManager(ClusterComputingManager, SSHComputingManag
             # Set pass if any
             authstring = ''
             if not task.requires_proxy_auth and task.password:
-                authstring = ' export SINGULARITYENV_AUTH_PASS={} && '.format(task.password)
+                authstring = ' && export SINGULARITYENV_AUTH_PASS={} '.format(task.password)
+
+            # Env vars if any
+            if task.container.env_vars:
+                varsstring = ''
+                # Sanitize again just in case the DB got somehow compromised:
+                env_vars = sanitize_container_env_vars(task.container.env_vars)
                 
+                for env_var in env_vars:
+                    varsstring += ' && export SINGULARITYENV_{}={} '.format(env_var, env_vars[env_var])
+            else:
+                varsstring = ''
+        
             # Handle storages (binds)
             binds = ''
             storages = Storage.objects.filter(computing=self.computing)
@@ -471,7 +513,7 @@ class SlurmSSHClusterComputingManager(ClusterComputingManager, SSHComputingManag
 
             run_command = 'ssh -o LogLevel=ERROR -i {} -4 -o StrictHostKeyChecking=no {}@{} '.format(computing_keys.private_key_file, computing_user, computing_host)
             run_command += '\'bash -c "echo \\"#!/bin/bash\nwget {}/api/v1/base/agent/?task_uuid={} -O \$HOME/agent_{}.py &> \$HOME/{}.log && export BASE_PORT=\\\\\\$(python \$HOME/agent_{}.py 2> \$HOME/{}.log) && '.format(webapp_conn_string, task.uuid, task.uuid, task.uuid, task.uuid, task.uuid)
-            run_command += 'export SINGULARITY_NOHTTPS=true && export SINGULARITYENV_BASE_PORT=\\\\\\$BASE_PORT && {} '.format(authstring)
+            run_command += 'export SINGULARITY_NOHTTPS=true && export SINGULARITYENV_BASE_PORT=\\\\\\$BASE_PORT {} {} && '.format(authstring, varsstring)
             run_command += 'rm -rf /tmp/{}_data && mkdir -p /tmp/{}_data/tmp &>> \$HOME/{}.log && mkdir -p /tmp/{}_data/home &>> \$HOME/{}.log && chmod 700 /tmp/{}_data && '.format(task.uuid, task.uuid, task.uuid, task.uuid, task.uuid, task.uuid)
             run_command += 'exec nohup singularity run {} --pid --writable-tmpfs --no-home --home=/home/metauser --workdir /tmp/{}_data/tmp -B/tmp/{}_data/home:/home --containall --cleanenv '.format(binds, task.uuid, task.uuid)
             
diff --git a/services/webapp/code/rosetta/core_app/migrations/0031_container_env_vars.py b/services/webapp/code/rosetta/core_app/migrations/0031_container_env_vars.py
new file mode 100644
index 0000000000000000000000000000000000000000..813af154081907a15393d903555ca126ede76b39
--- /dev/null
+++ b/services/webapp/code/rosetta/core_app/migrations/0031_container_env_vars.py
@@ -0,0 +1,25 @@
+# Generated by Django 2.2.1 on 2022-01-16 18:40
+
+from django.conf import settings
+from django.db import migrations
+
+# Load database-dependent JSON field
+if 'sqlite' in settings.DATABASES['default']['ENGINE']:
+    from rosetta.core_app.fields import JSONField
+else:
+    from django.contrib.postgres.fields import JSONField
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('core_app', '0030_auto_20211218_2355'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='container',
+            name='env_vars',
+            field=JSONField(blank=True, null=True, verbose_name='Container env vars'),
+        ),
+    ]
diff --git a/services/webapp/code/rosetta/core_app/models.py b/services/webapp/code/rosetta/core_app/models.py
index 5a886ac232448f72c87039f8a6c09ae3f5f76958..291e663c9b24e4260aec518559da700fed8d4d7b 100644
--- a/services/webapp/code/rosetta/core_app/models.py
+++ b/services/webapp/code/rosetta/core_app/models.py
@@ -141,6 +141,9 @@ class Container(models.Model):
     supports_interface_auth = models.BooleanField('Supports interface auth', default=False) # AUTH_USER / AUTH_PASS
     interface_auth_user = models.CharField('Interface auth fixed user if any', max_length=36, blank=True, null=True)
 
+    # Env vars for some container control
+    env_vars = JSONField('Container env vars', blank=True, null=True)
+
     class Meta:
         ordering = ['name']
 
diff --git a/services/webapp/code/rosetta/core_app/templates/add_software.html b/services/webapp/code/rosetta/core_app/templates/add_software.html
index 9487623e74a2b1b1f77e143603e2000732c25770..a18dd0675d39a253e267fbc66926d7eb337f3fad 100644
--- a/services/webapp/code/rosetta/core_app/templates/add_software.html
+++ b/services/webapp/code/rosetta/core_app/templates/add_software.html
@@ -135,6 +135,13 @@
             </td>
            </tr>
 
+           <tr>
+            <td><b>Environment variables</b></td>
+            <td>
+             ​<textarea name="container_env_vars" rows="2" cols="22" placeholder='JSON format: {"VAR"="VALUE"}'></textarea>
+            </td>
+           </tr>
+
           </table>
           </div>
           
diff --git a/services/webapp/code/rosetta/core_app/templates/components/container.html b/services/webapp/code/rosetta/core_app/templates/components/container.html
index 49a60652d435e4763dde73d6ce08664012acb593..ec99ff5f57819b7b5ecdca5ac0a0183d77a0b909 100644
--- a/services/webapp/code/rosetta/core_app/templates/components/container.html
+++ b/services/webapp/code/rosetta/core_app/templates/components/container.html
@@ -104,6 +104,12 @@
          {% endif %}        </td>
        </tr>
 
+       {% if container.env_vars %}
+       <tr>
+        <td><b>Env vars</b></td>
+        <td><pre>{{container.env_vars}}</pre></td>
+       </tr>
+       {% endif %}
        
        {% if container.user %}
        <tr>
diff --git a/services/webapp/code/rosetta/core_app/tests/test_utils.py b/services/webapp/code/rosetta/core_app/tests/test_utils.py
new file mode 100644
index 0000000000000000000000000000000000000000..f48fbdee8a3a1572695acc9645e48659487ae391
--- /dev/null
+++ b/services/webapp/code/rosetta/core_app/tests/test_utils.py
@@ -0,0 +1,34 @@
+import json
+
+from django.contrib.auth.models import User
+        
+from .common import BaseAPITestCase
+from ..utils import sanitize_container_env_vars
+
+class TestUtils(BaseAPITestCase):
+
+    def setUp(self):
+        pass
+
+    def test_sanitize_user_env_vars(self):
+        '''Test sanitize use env vars''' 
+        
+        # Basic
+        env_vars = {'myvar': 'a'}
+        self.assertEqual(sanitize_container_env_vars(env_vars),env_vars)
+
+        # Allowed specia
+        env_vars = {'myvar': '/a_directory/a-test'}
+        self.assertEqual(sanitize_container_env_vars(env_vars),env_vars)
+        
+        # Potential malicious
+        env_vars = {'myvar': '$(rm -rf)'}
+        with self.assertRaises(ValueError):
+            sanitize_container_env_vars(env_vars)
+            
+        
+         
+        
+        
+        
+
diff --git a/services/webapp/code/rosetta/core_app/utils.py b/services/webapp/code/rosetta/core_app/utils.py
index 1818e42164b174a4af42c0c4504c1b2e5da87790..b48a29d73724a7a10efb6afbc1b654efec9c3414 100644
--- a/services/webapp/code/rosetta/core_app/utils.py
+++ b/services/webapp/code/rosetta/core_app/utils.py
@@ -1,4 +1,5 @@
 import os
+import re
 import hashlib
 import traceback
 import hashlib
@@ -732,8 +733,13 @@ def get_ssh_access_mode_credentials(computing, user):
 
 
 
+def sanitize_container_env_vars(env_vars):
+    
+    for env_var in env_vars:
+        
+        # Check only alphanumeric chars, slashed, dashes and underscores
+        if not re.match("^[/A-Za-z0-9_-]*$", env_vars[env_var]):
+            raise ValueError('Value "{}" for env var "{}" is not valid: only alphanumeric, slashes, dashes and underscores are.'.format(env_vars[env_var], env_var))
 
-
-
-
+    return env_vars
 
diff --git a/services/webapp/code/rosetta/core_app/views.py b/services/webapp/code/rosetta/core_app/views.py
index 4605b3cdde4b554cb63c4fa8a62e706ffec30fbf..3961f733a3e6b8c63fe1d0996cd3945bf20887b3 100644
--- a/services/webapp/code/rosetta/core_app/views.py
+++ b/services/webapp/code/rosetta/core_app/views.py
@@ -11,7 +11,7 @@ from django.contrib.auth.models import User
 from django.shortcuts import redirect
 from django.db.models import Q
 from .models import Profile, LoginToken, Task, TaskStatuses, Container, Computing, KeyPair, Page
-from .utils import send_email, format_exception, timezonize, os_shell, booleanize, debug_param, get_task_tunnel_host, get_task_proxy_host, random_username, setup_tunnel_and_proxy, finalize_user_creation, get_md5
+from .utils import send_email, format_exception, timezonize, os_shell, booleanize, get_task_tunnel_host, get_task_proxy_host, random_username, setup_tunnel_and_proxy, finalize_user_creation, sanitize_container_env_vars
 from .decorators import public_view, private_view
 from .exceptions import ErrorMessage
 
@@ -951,6 +951,11 @@ def add_software(request):
         else:
             container_supports_pass_auth = False
 
+        # Environment variables
+        container_env_vars = request.POST.get('container_env_vars', None)
+        if container_env_vars:
+            container_env_vars = sanitize_container_env_vars(json.loads(container_env_vars))
+
         # Log
         #logger.debug('Creating new container object with image="{}", type="{}", registry="{}", ports="{}"'.format(container_image, container_type, container_registry, container_ports))
 
@@ -968,7 +973,8 @@ def add_software(request):
                                  interface_protocol  = container_interface_protocol,
                                  interface_transport = container_interface_transport,
                                  supports_custom_interface_port = container_supports_custom_interface_port,
-                                 supports_interface_auth = container_supports_pass_auth)
+                                 supports_interface_auth = container_supports_pass_auth,
+                                 env_vars = container_env_vars)
         # Set added switch
         data['added'] = True