1
+ #! /usr/bin/env bash
2
+ # -------------------------------------------------------------------------------------------------------------
3
+ # Copyright (c) Microsoft Corporation. All rights reserved.
4
+ # Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
5
+ # -------------------------------------------------------------------------------------------------------------
6
+
7
+ # Syntax: ./common-debian.sh [install zsh flag] [username] [user UID] [user GID] [upgrade packages flag]
8
+
9
+ INSTALL_ZSH=${1:- " true" }
10
+ USERNAME=${2:- " vscode" }
11
+ USER_UID=${3:- 1000}
12
+ USER_GID=${4:- 1000}
13
+ UPGRADE_PACKAGES=${5:- " true" }
14
+
15
+ set -e
16
+
17
+ if [ " $( id -u) " -ne 0 ]; then
18
+ echo -e ' Script must be run a root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
19
+ exit 1
20
+ fi
21
+
22
+ # Treat a user name of "none" as root
23
+ if [ " ${USERNAME} " = " none" ] || [ " ${USERNAME} " = " root" ]; then
24
+ USERNAME=root
25
+ USER_UID=0
26
+ USER_GID=0
27
+ fi
28
+
29
+ # Load markers to see which steps have already run
30
+ MARKER_FILE=" /usr/local/etc/vscode-dev-containers/common"
31
+ if [ -f " ${MARKER_FILE} " ]; then
32
+ echo " Marker file found:"
33
+ cat " ${MARKER_FILE} "
34
+ source " ${MARKER_FILE} "
35
+ fi
36
+
37
+ # Ensure apt is in non-interactive to avoid prompts
38
+ export DEBIAN_FRONTEND=noninteractive
39
+
40
+ # Function to call apt-get if needed
41
+ apt-get-update-if-needed ()
42
+ {
43
+ if [ ! -d " /var/lib/apt/lists" ] || [ " $( ls /var/lib/apt/lists/ | wc -l) " = " 0" ]; then
44
+ echo " Running apt-get update..."
45
+ apt-get update
46
+ else
47
+ echo " Skipping apt-get update."
48
+ fi
49
+ }
50
+
51
+ # Run install apt-utils to avoid debconf warning then verify presence of other common developer tools and dependencies
52
+ if [ " ${PACKAGES_ALREADY_INSTALLED} " != " true" ]; then
53
+ apt-get-update-if-needed
54
+
55
+ PACKAGE_LIST=" apt-utils \
56
+ git \
57
+ openssh-client \
58
+ gnupg2 \
59
+ iproute2 \
60
+ procps \
61
+ lsof \
62
+ htop \
63
+ net-tools \
64
+ psmisc \
65
+ curl \
66
+ wget \
67
+ rsync \
68
+ ca-certificates \
69
+ unzip \
70
+ zip \
71
+ nano \
72
+ vim-tiny \
73
+ less \
74
+ jq \
75
+ lsb-release \
76
+ apt-transport-https \
77
+ dialog \
78
+ libc6 \
79
+ libgcc1 \
80
+ libgssapi-krb5-2 \
81
+ libicu[0-9][0-9] \
82
+ liblttng-ust0 \
83
+ libstdc++6 \
84
+ zlib1g \
85
+ locales \
86
+ sudo \
87
+ ncdu \
88
+ man-db"
89
+
90
+ # Install libssl1.1 if available
91
+ if [[ ! -z $( apt-cache --names-only search ^libssl1.1$) ]]; then
92
+ PACKAGE_LIST=" ${PACKAGE_LIST} libssl1.1"
93
+ fi
94
+
95
+ # Install appropriate version of libssl1.0.x if available
96
+ LIBSSL=$( dpkg-query -f ' ${db:Status-Abbrev}\t${binary:Package}\n' -W ' libssl1\.0\.?' 2>&1 || echo ' ' )
97
+ if [ " $( echo " $LIBSSL " | grep -o ' libssl1\.0\.[0-9]:' | uniq | sort | wc -l) " -eq 0 ]; then
98
+ if [[ ! -z $( apt-cache --names-only search ^libssl1.0.2$) ]]; then
99
+ # Debian 9
100
+ PACKAGE_LIST=" ${PACKAGE_LIST} libssl1.0.2"
101
+ elif [[ ! -z $( apt-cache --names-only search ^libssl1.0.0$) ]]; then
102
+ # Ubuntu 18.04, 16.04, earlier
103
+ PACKAGE_LIST=" ${PACKAGE_LIST} libssl1.0.0"
104
+ fi
105
+ fi
106
+
107
+ echo " Packages to verify are installed: ${PACKAGE_LIST} "
108
+ apt-get -y install --no-install-recommends ${PACKAGE_LIST} 2> >( grep -v ' debconf: delaying package configuration, since apt-utils is not installed' >&2 )
109
+
110
+ PACKAGES_ALREADY_INSTALLED=" true"
111
+ fi
112
+
113
+ # Get to latest versions of all packages
114
+ if [ " ${UPGRADE_PACKAGES} " = " true" ]; then
115
+ apt-get-update-if-needed
116
+ apt-get -y upgrade --no-install-recommends
117
+ apt-get autoremove -y
118
+ fi
119
+
120
+ # Ensure at least the en_US.UTF-8 UTF-8 locale is available.
121
+ # Common need for both applications and things like the agnoster ZSH theme.
122
+ if [ " ${LOCALE_ALREADY_SET} " != " true" ]; then
123
+ echo " en_US.UTF-8 UTF-8" >> /etc/locale.gen
124
+ locale-gen
125
+ LOCALE_ALREADY_SET=" true"
126
+ fi
127
+
128
+ # Create or update a non-root user to match UID/GID - see https://aka.ms/vscode-remote/containers/non-root-user.
129
+ if id -u $USERNAME > /dev/null 2>&1 ; then
130
+ # User exists, update if needed
131
+ if [ " $USER_GID " != " $( id -G $USERNAME ) " ]; then
132
+ groupmod --gid $USER_GID $USERNAME
133
+ usermod --gid $USER_GID $USERNAME
134
+ fi
135
+ if [ " $USER_UID " != " $( id -u $USERNAME ) " ]; then
136
+ usermod --uid $USER_UID $USERNAME
137
+ fi
138
+ else
139
+ # Create user
140
+ groupadd --gid $USER_GID $USERNAME
141
+ useradd -s /bin/bash --uid $USER_UID --gid $USER_GID -m $USERNAME
142
+ fi
143
+
144
+ # Add add sudo support for non-root user
145
+ if [ " ${USERNAME} " != " root" ] && [ " ${EXISTING_NON_ROOT_USER} " != " ${USERNAME} " ]; then
146
+ echo $USERNAME ALL=\( root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME
147
+ chmod 0440 /etc/sudoers.d/$USERNAME
148
+ EXISTING_NON_ROOT_USER=" ${USERNAME} "
149
+ fi
150
+
151
+ # .bashrc/.zshrc snippet
152
+ RC_SNIPPET=" $( cat << EOF
153
+ export USER=\$ (whoami)
154
+
155
+ export PATH=\$ PATH:\$ HOME/.local/bin
156
+
157
+ if [[ \$ (which code-insiders 2>&1) && ! \$ (which code 2>&1) ]]; then
158
+ alias code=code-insiders
159
+ fi
160
+ EOF
161
+ ) "
162
+
163
+ # Ensure ~/.local/bin is in the PATH for root and non-root users for bash. (zsh is later)
164
+ if [ " ${RC_SNIPPET_ALREADY_ADDED} " != " true" ]; then
165
+ echo " ${RC_SNIPPET} " >> /etc/bash.bashrc
166
+ RC_SNIPPET_ALREADY_ADDED=" true"
167
+ fi
168
+
169
+ # Optionally install and configure zsh
170
+ if [ " ${INSTALL_ZSH} " = " true" ] && [ ! -d " /root/.oh-my-zsh" ] && [ " ${ZSH_ALREADY_INSTALLED} " != " true" ]; then
171
+ apt-get-update-if-needed
172
+ apt-get install -y zsh
173
+ curl -fsSLo- https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh | bash 2>&1
174
+ echo " ${RC_SNIPPET} " >> /etc/zsh/zshrc
175
+ echo -e " DEFAULT_USER=\$ USER\nprompt_context(){}" >> /root/.zshrc
176
+ cp -fR /root/.oh-my-zsh /etc/skel
177
+ cp -f /root/.zshrc /etc/skel
178
+ sed -i -e " s/\/root\/.oh-my-zsh/\/home\/\$ (whoami)\/.oh-my-zsh/g" /etc/skel/.zshrc
179
+ if [ " ${USERNAME} " != " root" ]; then
180
+ cp -fR /etc/skel/.oh-my-zsh /etc/skel/.zshrc /home/$USERNAME
181
+ chown -R $USER_UID :$USER_GID /home/$USERNAME /.oh-my-zsh /home/$USERNAME /.zshrc
182
+ fi
183
+ ZSH_ALREADY_INSTALLED=" true"
184
+ fi
185
+
186
+ # Write marker file
187
+ mkdir -p " $( dirname " ${MARKER_FILE} " ) "
188
+ echo -e " \
189
+ PACKAGES_ALREADY_INSTALLED=${PACKAGES_ALREADY_INSTALLED} \n\
190
+ LOCALE_ALREADY_SET=${LOCALE_ALREADY_SET} \n\
191
+ EXISTING_NON_ROOT_USER=${EXISTING_NON_ROOT_USER} \n\
192
+ RC_SNIPPET_ALREADY_ADDED=${RC_SNIPPET_ALREADY_ADDED} \n\
193
+ ZSH_ALREADY_INSTALLED=${ZSH_ALREADY_INSTALLED} " > " ${MARKER_FILE} "
194
+
195
+ echo " Done!"
0 commit comments