cdn-django/install.sh
raw link view readme| 1 | STORAGE_KEY=$2 |
| 2 | DNS_NAME=$3 |
| 3 | CDN_ROOT=$4.azureedge.net |
| 4 | |
| 5 | yum install epel-release -y |
| 6 | |
| 7 | yum install policycoreutils-python -y |
| 8 | semanage fcontext -at httpd_sys_rw_content_t "/srv/cdndjango(/.*)?" |
| 9 | semanage fcontext -at httpd_sys_content_t "/srv/common(/.*)?" |
| 10 | |
| 11 | yum install firewalld -y |
| 12 | systemctl start firewalld |
| 13 | systemctl enable firewalld |
| 14 | firewall-cmd --permanent --zone=public --add-interface=eth0 |
| 15 | firewall-cmd --permanent --add-service=http --add-service=https --zone=public |
| 16 | firewall-cmd --reload |
| 17 | |
| 18 | # Just for testing... |
| 19 | |
| 20 | mkdir /srv/common |
| 21 | cat > /srv/common/robots.txt << EOF |
| 22 | User-agent: ia_archiver |
| 23 | Disallow: / |
| 24 | EOF |
| 25 | |
| 26 | # UWSGI |
| 27 | |
| 28 | yum install uwsgi uwsgi-plugin-python3 -y |
| 29 | |
| 30 | cat > /etc/uwsgi.d/cdndjango.ini << EOF |
| 31 | [uwsgi] |
| 32 | project = engine |
| 33 | base = /srv/cdndjango/site |
| 34 | virtualenv = /srv/cdndjango |
| 35 | |
| 36 | chdir = %(base) |
| 37 | home = %(virtualenv) |
| 38 | module = %(project).core.wsgi:application |
| 39 | |
| 40 | master = true |
| 41 | processes = 5 |
| 42 | |
| 43 | socket = %(base)/%(project).sock |
| 44 | chmod-socket = 660 |
| 45 | uid = uwsgi |
| 46 | gid = uwsgi |
| 47 | vacuum = true |
| 48 | |
| 49 | plugins = python3 |
| 50 | EOF |
| 51 | |
| 52 | chown -R nobody:uwsgi /etc/uwsgi.d |
| 53 | chmod -R g+s /etc/uwsgi.d |
| 54 | |
| 55 | # App |
| 56 | |
| 57 | yum install python34 python-pip -y 2> /dev/null |
| 58 | pip install --upgrade pip |
| 59 | pip install --upgrade virtualenv |
| 60 | cd /srv |
| 61 | virtualenv -p python3 cdndjango |
| 62 | chmod -R 2750 /srv/cdndjango |
| 63 | setfacl -m d:o:--- /srv/cdndjango |
| 64 | cd /srv/cdndjango |
| 65 | source bin/activate |
| 66 | mkdir site |
| 67 | cd site |
| 68 | |
| 69 | mkdir -p engine/core |
| 70 | mkdir templates |
| 71 | |
| 72 | cat > ./requirements.txt << EOF |
| 73 | Django==1.10.1 |
| 74 | EOF |
| 75 | |
| 76 | pip install -r requirements.txt |
| 77 | |
| 78 | cat > ./engine/core/views.py << EOF |
| 79 | from django.shortcuts import render |
| 80 | from engine import settings as engine_settings |
| 81 | |
| 82 | def process(request): |
| 83 | render_data = { |
| 84 | 'title': 'random demo', |
| 85 | 'cdn': engine_settings.CDN_ROOT.replace('https:', '') |
| 86 | } |
| 87 | |
| 88 | return render(request, ['index.html', 'index.htm'], render_data) |
| 89 | |
| 90 | EOF |
| 91 | |
| 92 | cat > ./engine/core/__init__.py << EOF |
| 93 | EOF |
| 94 | |
| 95 | cat > ./engine/core/wsgi.py << EOF |
| 96 | import os |
| 97 | from django.core.wsgi import get_wsgi_application |
| 98 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "engine.settings") |
| 99 | application = get_wsgi_application() |
| 100 | EOF |
| 101 | |
| 102 | cat > ./engine/core/urls.py << EOF |
| 103 | from django.conf.urls import url |
| 104 | import sys |
| 105 | |
| 106 | from . import views |
| 107 | |
| 108 | class CoreUrl: |
| 109 | def init(self): |
| 110 | pass |
| 111 | |
| 112 | def setup(self): |
| 113 | self.urlpatterns = [ |
| 114 | url(r'^$', views.process), |
| 115 | ] |
| 116 | |
| 117 | return self.urlpatterns |
| 118 | |
| 119 | urlpatterns = CoreUrl().setup() |
| 120 | EOF |
| 121 | |
| 122 | cat > ./engine/__init__.py << EOF |
| 123 | EOF |
| 124 | |
| 125 | cat > ./engine/settings.py << EOF |
| 126 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...) |
| 127 | import os, sys |
| 128 | |
| 129 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) |
| 130 | |
| 131 | SECRET_KEY = 'whatever8786ubhj8giyhbjhuiybhuhu08h9ui38u084hubj' |
| 132 | |
| 133 | DEBUG = True |
| 134 | |
| 135 | ALLOWED_HOSTS = ['127.0.0.1', 'localhost', 'does.nothing.in.debug.mode'] |
| 136 | |
| 137 | INSTALLED_APPS = ( |
| 138 | 'engine', |
| 139 | 'engine.core', |
| 140 | 'django.contrib.auth', |
| 141 | 'django.contrib.contenttypes', |
| 142 | 'django.contrib.messages', |
| 143 | ) |
| 144 | |
| 145 | MIDDLEWARE_CLASSES = ( |
| 146 | 'django.middleware.common.CommonMiddleware', |
| 147 | ) |
| 148 | |
| 149 | ROOT_URLCONF = 'engine.core.urls' |
| 150 | |
| 151 | ROOT_PATH = os.path.split(os.path.abspath(__file__))[0] |
| 152 | |
| 153 | TEMPLATES = [ |
| 154 | { |
| 155 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', |
| 156 | 'DIRS': [ |
| 157 | os.path.join(BASE_DIR, 'templates') |
| 158 | ], |
| 159 | 'OPTIONS': { |
| 160 | 'context_processors': [ |
| 161 | 'django.template.context_processors.debug', |
| 162 | 'django.template.context_processors.request', |
| 163 | 'django.contrib.auth.context_processors.auth', |
| 164 | 'django.contrib.messages.context_processors.messages', |
| 165 | ], |
| 166 | 'loaders': [ |
| 167 | ('django.template.loaders.cached.Loader', [ |
| 168 | 'django.template.loaders.filesystem.Loader', |
| 169 | 'django.template.loaders.app_directories.Loader', |
| 170 | ]), |
| 171 | ], |
| 172 | }, |
| 173 | }, |
| 174 | ] |
| 175 | |
| 176 | PROJECT_DIR = os.path.dirname(__file__) |
| 177 | |
| 178 | STATICFILES_DIRS = ( |
| 179 | os.path.join(PROJECT_DIR, 'static'), |
| 180 | ) |
| 181 | |
| 182 | LANGUAGE_CODE = 'en-us' |
| 183 | |
| 184 | TIME_ZONE = 'UTC' |
| 185 | |
| 186 | USE_I18N = True |
| 187 | |
| 188 | USE_L10N = True |
| 189 | |
| 190 | USE_TZ = True |
| 191 | |
| 192 | DOMAIN = 'https://does.not.matter' |
| 193 | |
| 194 | # the web doesn't have folders; this isn't 1994 |
| 195 | APPEND_SLASH = False |
| 196 | |
| 197 | application_root = '/' |
| 198 | |
| 199 | CDN_ROOT = '$CDN_ROOT' |
| 200 | |
| 201 | EOF |
| 202 | |
| 203 | cat > ./manage.py << EOF |
| 204 | #!/usr/bin/env python2 |
| 205 | import os |
| 206 | import sys |
| 207 | |
| 208 | if __name__ == "__main__": |
| 209 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "engine.settings") |
| 210 | |
| 211 | from django.core.management import execute_from_command_line |
| 212 | |
| 213 | execute_from_command_line(sys.argv) |
| 214 | |
| 215 | EOF |
| 216 | |
| 217 | cat > ./runserver.sh << EOF |
| 218 | python manage.py runserver 127.0.0.1:8081 --settings=engine.settings |
| 219 | EOF |
| 220 | chmod +x ./runserver.sh |
| 221 | |
| 222 | cat > ./templates/index.html << EOF |
| 223 | |
| 224 | |
| 225 | |
| 226 | |
| 227 | |
| 228 | |
| 229 | |
| 230 | |
| 231 | {{ title }} |
| 232 | |
| 233 | |
| 234 | |
| 235 | Here is my content. The CDN is up and running when this is blue. |
| 236 | |
| 237 | |
| 238 | |
| 239 | |
| 240 | EOF |
| 241 | |
| 242 | deactivate |
| 243 | |
| 244 | chown -R nobody:uwsgi /srv/cdndjango |
| 245 | restorecon -R /srv |
| 246 | |
| 247 | #Nginx |
| 248 | |
| 249 | cat > /etc/yum.repos.d/nginx.repo << EOF |
| 250 | [nginx] |
| 251 | name=nginx repo |
| 252 | baseurl=http://nginx.org/packages/mainline/centos/\$releasever/\$basearch/ |
| 253 | gpgcheck=0 |
| 254 | enabled=1 |
| 255 | EOF |
| 256 | |
| 257 | yum install -y nginx |
| 258 | |
| 259 | export PUBLIC_IP=$(ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1 -d'/') |
| 260 | |
| 261 | mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.disabled |
| 262 | cat > /etc/nginx/conf.d/cdndjango.conf << EOF |
| 263 | server { |
| 264 | listen $PUBLIC_IP:80; |
| 265 | |
| 266 | location /robots.txt { |
| 267 | alias /srv/common/robots.txt; |
| 268 | } |
| 269 | |
| 270 | location / { |
| 271 | include uwsgi_params; |
| 272 | uwsgi_pass unix:/srv/cdndjango/site/engine.sock; |
| 273 | |
| 274 | proxy_redirect off; |
| 275 | proxy_set_header Host \$host; |
| 276 | proxy_set_header X-Real-IP \$remote_addr; |
| 277 | proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; |
| 278 | proxy_set_header X-Forwarded-Host \$server_name; |
| 279 | } |
| 280 | } |
| 281 | EOF |
| 282 | |
| 283 | usermod nginx -aG uwsgi |
| 284 | |
| 285 | systemctl start uwsgi |
| 286 | systemctl enable uwsgi |
| 287 | |
| 288 | systemctl start nginx |
| 289 | systemctl enable nginx |
| 290 | |
| 291 | cat > /tmp/site.css <<\EOF |
| 292 | p > span > span { |
| 293 | color: #00f; |
| 294 | } |
| 295 | EOF |
| 296 | |
| 297 | yum install openssl-devel python-devel gcc -y |
| 298 | cd /srv |
| 299 | # azure storage still requires legacy python (aka python2) |
| 300 | virtualenv assetuploader |
| 301 | cd /srv/assetuploader |
| 302 | source bin/activate |
| 303 | pip install azure-storage |
| 304 | mkdir app |
| 305 | cd app |
| 306 | cat > upload.py << EOF |
| 307 | from azure.common import AzureMissingResourceHttpError |
| 308 | from azure.storage.blob import BlockBlobService, ContentSettings, PublicAccess |
| 309 | from azure.storage import CorsRule |
| 310 | |
| 311 | blob_service = BlockBlobService(account_name='$STORAGE_NAME', account_key='$STORAGE_KEY') |
| 312 | |
| 313 | content_settings = ContentSettings() |
| 314 | content_settings.content_type = 'text/css' |
| 315 | |
| 316 | blob_service.create_container('css', public_access=PublicAccess.Blob) |
| 317 | with open('/tmp/site.css', 'r') as f: |
| 318 | blob_service.create_blob_from_bytes('css', 'site.css', f.read(), content_settings=content_settings) |
| 319 | |
| 320 | blob_service.set_blob_service_properties(cors=[CorsRule( |
| 321 | allowed_origins=['$DNS_NAME'], |
| 322 | allowed_methods=['GET'], |
| 323 | allowed_headers = ['*'], |
| 324 | exposed_headers = ['*'], |
| 325 | max_age_in_seconds = 1800 |
| 326 | )]) |
| 327 | EOF |
| 328 | chmod 0600 upload.py |
| 329 | |
| 330 | python upload.py |
| 331 | deactivate |
| 332 |