• Минимальные настройки безопасности Linux на VPS?

    Tyranron
    @Tyranron
    Ряд моментов Вы уже сделали, но я все равно их опишу для полноты списка.

    1. Создать отдельного пользователя и хороший пароль на sudo. Не использовать больше root напрямую. Совсем.

    2. SSH. Отключаем метод аутентификации по паролю. Если Вам не нужны другие методы, то их тоже можно отключить, оставив только publickey. Отключаем возможность аутентификации root'ом. Включаем использование только 2й версии SSH протокола.

    3. Устанавливаем Fail2Ban и настраиваем чтобы после нескольких неуспешных попыток подключения по SSH банило по IP на длительное время. Кол-во попыток и время бана можно тюнить в меру своей паранойи. У меня, например, банит на час после 2х неуспешных попыток.

    4. Iptables. Действуем по принципу "запрещено все, что не разрешено". Запрещаем по умолчанию весь INPUT и FORWARD трафик снаружи. Открываем на INPUT'е 22 порт. В дальнейшем открываем порты/forwarding по мере необходимости. Если у нас предполагаются сервисы на соседних серверах нужные только для внутренней коммуникации (Memcached, Redis, и т.д.), то открываем для них порты только для определенных IP. Просто так торчать наружу для всех они не должны.

    5. Настраиваем автоматические обновления apt-пакетов. Уровень security. То есть так, чтобы обновления безопасности накатывались автоматически, но при этом не выполнялись обновления со сменой мажорной версии (дабы обезопасить себя от "само сломалось").

    6. Устанавливаем ntpd. Серверное время должно быть точным. Также временную зону сервера лучше всего установить в UTC.

    7. TLS (не SSL) используем везде где можем. Через Let's Encrypt получаем бесплатные валидные сертификаты. В конфигах веб-серверов, mail-серверов, и других приложений торчащих наружу (в том числе и OpenVPN), запрещаем/убираем использование слабых шифров. Все ключи/параметры генерируем не менее 2048 бит. Самоподписные сертификаты подписываем с помощью SHA-256 (не SHA-1). Diffie-Hellman параметры (dh.pem) под каждый сервис лучше сгенерить отдельно. Проверяем TLS сервисов через Nmap. Минимальный grade должен быть A, не должно быть warning'ов.

    8. Правильный менеджмент пользователей/групп. Приложения/сервисы не должны запускаться под root'ом (разве что они действительно этого требуют и иначе никак). Для каждого сервиса создается свой пользователь.

    9. Если предполагается upload файлов через PHP (либо другие скриптовые языки), в директории, куда эти файлы загружаются (и которая доступна снаружи), должно быть жестко отключено любое выполнение скриптов/бинарников, что на уровне ОС (x права), что на уровне веб-сервера.

    Это была база.
    Дальше, в меру своей паранойи можно за'harden'ить сервер ещё следующими моментами:
    - SELinux, chroot
    - доступ к SSH только с определенных IP (нужно иметь 3-4 VPN-сервера под рукой)

    UPD И да, все это помнить/настраивать руками каждый раз может быть запарно. Используйте Ansible и автоматизируйте процесс (там родные и YAML, Jinja2 и Python).
    Ответ написан
    10 комментариев
  • Какие проекты может потянуть один человек?

    @MaratN
    Встречаются два друга:
    — Как дела?
    — Да вот, основал новый стартап, очень быстро растём, развиваемся.
    — Круто! А в чём суть стартапа?
    — Я провёл исследование рынка и решил публичный дом открыть.
    — Ого, интересно, и какие цены?
    — Анал — $100, орал — $50.
    — А классический секс?
    — Понимаешь, с этим труднее... это ж стартап. В общем, я пока один работаю…
    Ответ написан
    Комментировать
  • Куда уходят наработки и код от неудачных стартапов?

    sim3x
    @sim3x
    /dev/null
    Ответ написан
    Комментировать
  • Какие проекты может потянуть один человек?

    Neznayka1979
    @Neznayka1979
    Интересы - IT, психология...
    6c7e635425e24eda90fd4ac9d80c9adb.gif

    Маргарет Гамильтон стоит рядом с написанным ей исходным кодом бортового компьютера «Аполлона»
    Ответ написан
    11 комментариев
  • "Норматив верстки", какой он?

    @abbrakadabbra
    У клиента мало денег, с таким бюджетом он еще хочет контролировать каждый вас шаг. Обычно с такими клиентами можно поиметь проблем, ибо они пекутся за каждую копейку и не доверяют.

    Не знаю какая сложность у макета, но 5 долларов за час - не высокая расценка на сегодняшний день. И в целом 30 долларов за работу.

    Можно взять для портфолио, и даже выполнить под присмотром (но договоритесь, чтобы можно было хоть отдохнуть, а то этот извращенец потом выставит вам претензию, что вы не выполнили условия). В случае если примете проект, то убедитесь, что клиент адекватен, обсудите все пункты сотрудничества.

    С бутстрапом справитесь быстрее (если нужна респонсив верстка, и всякие табы, эффекты).
    Ответ написан
    4 комментария
  • Можно ли заработать в мире Unix-like, unix-way?

    @Z-r
    Мне известно четыре основных способа заработка, напрямую связанных со свободными программами:

    — Первый, самый прямой, но от того почему-то всем не менее неочевидный — брать и продавать копии свободных программ. Аудитория: любые конечные пользователи. Примеры: Parted Magic, ряд программок для «Андроида», ну например, «Conversations». Высокоморальность: в полном порядке.

    — Второй — это уже известная вами продажа поддержки. А фактически иногда и просто своего имени, когда какая-то реальная поддержка начинается с сумм несколько больших, чем базовый контракт. Аудитория: те, для кого ваша программа есть орудие производства, то есть компании и предприниматели. Пример: уже озвученный вами Canonical. Высокоморальность: в полном порядке.

    — Третий — это продажа исключений из авторского лева. Аудиторией будут разработчики несвободных программ, а программа ваша должна быть библиотекой под (как нетрудно догадаться) авторским левом, причем чаще сильным. Суть в том, что для добрых людей ваш продукт свободен на условиях, скажем, GNU GPL или GNU AGPL, а проприетарщики пусть платят за возможность использовать его в своих шкурных интересах. Примеры: GhostScript, MySQL. Высокоморльность: прихрамывает маленько.

    — Четвертый — это то, о чем помянул тов. CityCat4 — т. н. free crippleware, то есть полноценная ваша программа несвободна и платна, но у нее есть свободный урезанный вариант. Причем урезано может быть как что-то существенное, так и сущая ерунда. Аудитория: кто угодно. Примеры: Odoo, GitLab, ProcessMaker. Высокоморальность: от невысокой до никакой, смотря сколько отрезано.

    И разумеется, все вышеперечисленно можно комбинировать: Qt, к примеру, и поддержку (обучение) предоставляет, и исключения из авторского лева (причем слабого!) продает, и совсем ерундовую несвободную часть имеет. А упомянутый вами Red Hat — продает копии и предоставляет поддержку. А иногда и такое бывает: программка для «Андроида» под названием OsmAnd полностью свободна, но поставляется в Гуглоплэе в двух вариантах: полном за копеечку и урезанном бесплатно. Еще раз: обе версии свободны, то есть никакой моральной проблемы здесь нет.

    ――

    P. S. Я перечислил только способы заработка на программах как таковых, полагая, что схемы, где свободные программы участвуют косвенно, и без того очевидны, но в комментариях только о них и говорят, так что надо, наверное, упомянуть, что да, конечно, свободная программа также может быть:
    — Частью продаваемой услуги — чаще всего услуги специфического хостинга, как ставимый здесь в пример Openshift или (если ближе к народу) Feedly.
    — Частью продаваемого устройства, причем само устройство может быть как свободным, так и нет. Тысячи их.
    — И наконец, просто частью приносящего прибыль техпроцесса. То есть компания пишет (заказывает) программу себе для внутреннего использования и могла бы ее вообще не распространять, но, не считая ее своим «ноу-хау», ведет себя благородно и просто свободно делится ею со всеми. Известнейший пример — Reddit (хотя в последнее время они подскурвились).

    ――

    И не могу все-таки не отметить, что unix-way отношение к свободе имеет такое же, как мелкое к горячему.
    Ответ написан
    2 комментария
  • Можно ли заработать в мире Unix-like, unix-way?

    @LiguidCool
    И еще хотелось бы остаться на платформе до конца, а не переучиваться через 5-10 лет.

    Хехе, наивный :)
    10 лет назад скажи народу, что на JS будут сервер писать - засмеяли бы. А лет 15 назад пфф. Я уж не говорю у мобильной разработке, которая расцвела полным ходом. Да и даже веб сильно изменился.
    Как именно там зарабатывают обычные люди, разработчики

    Также как и все - работают на дядю и зарабатывают. А на чем дядя зарабатывает, на том и вы.

    На самом деле все очень по разному... Да и большое заблуждение, что Unix-way = бесплатно. Хм ... Ну например 1С для Linux - ОС бесплатная, но ПО под него нет.

    Если я лицензирую свой код GPLv2/3(и совместимыми), то как на этом зарабатывать?

    Платная поддержка по подписке. Или например сейчас можно делать для опенсурсной платформы платное облако. Хочешь - себе ставь бесплатно, хочешь плати и тебе все из коробочки всучат.

    У меня закралось подозрение, что ... "Если я лицензирую свой код GPLv2/3" - вы что, думаете вам начальник разрешит? :D Или стооооп, вы надеетесь работать на себя в карман? На Сях? Не ну удачи, она вам точно понадобится.

    PS
    На правах ИМХО.
    Ответ написан
    3 комментария
  • Где и как хранить тестовые сайты?

    @tagplus5
    Сервер на digitalocean
    - направляем на него домен *.site.com
    - каждый проект в своем docker контейнере со своим окружением
    - docker контейнер с nginx (прописываем поддомены)
    - контейнер/ы c бд.

    Разворачивать можно с помощью git ruhighload.com/post/Git+%D0%B4%D0%BB%D1%8F+%D1%80%...

    Если много новых проектов, можно сделать автосоздание поддомена для каждого нового контейнера.
    Ответ написан
    Комментировать
  • Где и как хранить тестовые сайты?

    @mr_ko
    Javascript, Node.js. React.js, Vue.js, Wordpress
    Для онлайн демонстрации держу минимальную VDSку и левый домен на котором висят тестовые поддомены.
    А это, насколько мне известно, не очень круто для поисковиков.

    Для этого существует файл robots.txt
    Ответ написан
    Комментировать
  • Быстрый LIKE по 1 миллиону строк, как быть?

    Sanasol
    @Sanasol Куратор тега PHP
    нельзя просто так взять и загуглить ошибку
    sphinx использовать.
    или https://dadata.ru/
    Ответ написан
    6 комментариев
  • Как организован workflow фронтенд разработчика?

    serjikz
    @serjikz
    web-developer
    Давайте по пунктам постараюсь рассказать, как вообще надо работать во front-end.
    1. Вы должны научиться думать блоками (блоками в потоке, выпадающими из потока, flex-блоками и тд и тп). Научиться можно только когда вы поймете как на самом деле надо верстать.
    2. Начните с простой вёрстки. Возьмите макет в .psd (80% работы над каждым сайтом вы будете пользоваться PhotoShop и если вы его не знаете хотя бы на предбазовом уровне - печаль беда), импортируйте оттуда все нужные вам картинки ну и начинайте верстать шаблон поблочно, смотря где какой цвет шрифта, размер, жирность, размер блока, фон этого блока и тд и тп.
    3. Зачем вы себе морочили голову gulp, sass, bootstrap когда ещё верстать даже нормально не умеете - я увы не понимаю. Вам ни один из этих инструментов не поможет пока вы не будете уметь именно верстать. На данный момент не думайте о технологиях, структуре и тд и тп. Просто сверстайте хоть какой-нибудь макет хоть как-то.
    4. Общайтесь с людьми, которые вам могут помочь продвинуться в этой сфере. Таковых крайне много. Можете ко мне в скайп добавиться и узнавать некоторые вещи, можете к другим, к кому угодно фактически, наверно 60-70% верстальщиков с удовольствием поделятся с вами своим опытом
    5. Пишите код аккуратно. Был тут недавно вопрос, в котором человек предоставил код, а там ни{ } нету, ни отступов нормальных нет, ну и половина ; просто потеряны, а в html теги применяются не по назначению вовсе. Нельзя так делать ни в коем случае, иначе ваш уровень не поднимется с уровня плинтуса.
    6. Файловая структура: папки css images js и на уровне с этими папками лежат файлы .html либо .php всё. Если говорить о препроцессорах и сборщиках - не лезте пока в это, потом узнаете как только научитесь нормально верстать. Я думаю нет смысла объяснять что в папках тех должно лежать. Если вы считаете себя особенным - можете распределять внутри images картинки по папкам на составляющие, к примеру сделать папку отзывов, папку галерей каких-нибудь и тп, но я чаще так не делаю, не хочу чтоб дополнительные символы засоряли мне код и ухудшали читаемость.
    7. Связывать между собой html и css судя по всему вы и так уже умеете и привязывать к ним js. Не знаю что вам мешает сверстать любой сайт если вы понимаете как устроены эти 3 технологии (а на них по факту всё и держится).

    Итог: Забудьте про sass, gulp и прочее пока не сверстаете шаблонов 10, эти технологии вас никак не ускорят и никак вам не помогут пока вы не будете уметь просто верстать с шаблона .psd и писать нужные скрипты на js или jQuery хотя бы. Научитесь немного фотошопу и занимайтесь практикой. Найти те самые .psd вообще не проблема, их куча бесплатных в интернете.
    Ответ написан
    2 комментария
  • Пересекаются ли аккаунты в Google?

    anthtml
    @anthtml
    Системный администратор программист радиолюбитель
    Кнопка "добавить аккаунт" сделана для того чтобы быстро переключаться на сайте между разными акками, к примеру между личным и рабочим, корпоративным. Она дает только то что не надо при каждом переключении разлогиниваться и залогиниваться по новой, а просто нажать кнопку "Перейти в другой аккаунт". Между собой акки никак не связываются.
    Ответ написан
    Комментировать
  • Как в Google Chrome убрать уведомление "отключение расширений в режиме разработчика"?

    @wOxxOm
    Батник-патчер, убирающий это принудительное предупреждение:

    1. Скопируйте код ниже и сохраните в любом текстовом редакторе как, например, DevWarningPatch.bat на рабочем столе

    2. Закройте хром вручную, чтобы не потерять незаконченное письмо, например, батник сам завершит оставшиеся спрятанные процессы хрома принудительно.

    3. Нажмите правой кнопкой мыши на сохраненном файле и запустите его от имени администратора, чтобы пропатчить все установленные версии хрома (поиск осуществляется посредством реестра или в текущей папке).

    Также можно просто перетянуть chrome.dll из папки портабельного хрома на иконку батника.

    <# :
    @echo off
    copy/b "%~f0" "%temp%\%~n0.ps1" >nul
    powershell -Version 2 -ExecutionPolicy bypass -noprofile "%temp%\%~n0.ps1" "%cd% " "%~1"
    del "%temp%\%~n0.ps1"
    pause
    exit /b
    #>
    param([string]$cwd='.', [string]$dll)
    
    function main {
        "Chrome 'developer mode extensions' warning disabler v1.0.10.20170114`n"
        $pathsDone = @{}
        if ($dll -and (gi -literal $dll)) {
            doPatch "DRAG'n'DROPPED" ((gi -literal $dll).directoryName + '\')
            exit
        }
        doPatch CURRENT ((gi -literal $cwd).fullName + '\')
        ('HKLM', 'HKCU') | %{ $hive = $_
            ('', '\Wow6432Node') | %{
                $key = "${hive}:\SOFTWARE$_\Google\Update\Clients"
                gci -ea silentlycontinue $key -r | gp | ?{ $_.CommandLine } | %{
                    $path = $_.CommandLine -replace '"(.+?\\\d+\.\d+\.\d+\.\d+\\).+', '$1'
                    doPatch REGISTRY $path
                }
            }
        }
    }
    
    function doPatch([string]$pathLabel, [string]$path) {
        if ($pathsDone[$path.toLower()]) { return }
    
        $dll = $path + "chrome.dll"
        if (!(test-path -literal $dll)) {
            return
        }
        "======================="
        "$pathLabel PATH $((gi -literal $dll).DirectoryName)"
    
        "`tREADING Chrome.dll..."
        $bytes = [IO.File]::ReadAllBytes($dll)
    
        # process PE headers
        $BC = [BitConverter]
        $coff = $BC::ToUInt32($bytes,0x3C) + 4
        $is64 = $BC::ToUInt16($bytes,$coff) -eq 0x8664
        $opthdr = $coff+20
        $codesize = $BC::ToUInt32($bytes,$opthdr+4)
        $imagebase32 = $BC::ToUInt32($bytes,$opthdr+28)
    
        # patch the flag in data section
        $data = $BC::ToString($bytes,$codesize)
        $flag = "ExtensionDeveloperModeWarning"
        $stroffs = $data.IndexOf($BC::ToString($flag[1..99]))/3 - 1
        if ($stroffs -lt 0) {
            write-host -f red "`t$flag not found"
            return
        }
        $stroffs += $codesize
        if ($bytes[$stroffs] -eq 0) {
            write-host -f darkgreen "`tALREADY PATCHED"
            return
        }
    
        $exe = join-path (split-path $path) chrome.exe
        $EA = $ErrorActionPreference
        $ErrorActionPreference = 'silentlyContinue'
        while ((get-process chrome -module | ?{ $_.FileName -eq $exe })) {
            forEach ($timeout in 15..0) {
                write-host -n -b yellow -f black `
                    "`rChrome is running and will be terminated in $timeout sec. "
                write-host -n -b yellow -f darkyellow "Press ENTER to do it now. "
                if ([console]::KeyAvailable) {
                    $key = $Host.UI.RawUI.ReadKey("AllowCtrlC,IncludeKeyDown,NoEcho")
                    if ($key.virtualKeyCode -eq 13) { break }
                    if ($key.virtualKeyCode -eq 27) { write-host; exit }
                }
                sleep 1
            }
            write-host
            get-process chrome | ?{
                $_.MainWindowHandle.toInt64() -and ($_ | gps -file).FileName -eq $exe
            } | %{
                "`tTrying to exit gracefully..."
                if ($_.CloseMainWindow()) {
                    sleep 1
                }
            }
            $killLabelShown = 0
            get-process chrome | ?{
                ($_ | gps -file | select -expand FileName) -eq $exe
            } | %{
                if (!$killLabelShown++) {
                    "`tTerminating background chrome processes..."
                }
                stop-process $_ -force
            }
            sleep -milliseconds 200
        }
        $ErrorActionPreference = $EA
    
        $bytes[$stroffs] = 0
        "`tPATCHED $flag flag"
    
        # patch the channel restriction code for stable/beta
        $code = $BC::ToString($bytes,0,$codesize)
        $rxChannel = '83-F8-(?:03-7D|02-7F)'
        # old code: cmp eax,3; jge ...
        # new code: cmp eax,2; jg ...
        $chanpos = 0
        try {
            if ($is64) {
                $pos = 0
                $rx = [regex]"$rxChannel-.{1,100}-48-8D"
                do {
                    $m = $rx.match($code,$pos)
                    if (!$m.success) { break }
                    $chanpos = $m.index/3 + 2
                    $pos = $m.index + $m.length + 1
                    $offs = $BC::ToUInt32($bytes,$pos/3+1)
                    $diff = $pos/3+5+$offs - $stroffs
                } until ($diff -ge 0 -and $diff -le 4096 -and $diff % 256 -eq 0)
                if (!$m.success) {
                    $rx = [regex]"84-C0.{18,48}($rxChannel)-.{30,60}84-C0"
                    $m = $rx.matches($code)
                    if ($m.count -ne 1) { throw }
                    $chanpos = $m[0].groups[1].index/3 + 2
                }
            } else {
                $flagOffs = [uint32]$stroffs + [uint32]$imagebase32
                $flagOffsStr = $BC::ToString($BC::GetBytes($flagOffs))
                $variants = "(?<channel>$rxChannel-.{1,100})-68-(?<flag>`$1-.{6}`$2)",
                        "68-(?<flag>`$1-.{6}`$2).{300,500}E8.{12,32}(?<channel>$rxChannel)",
                        "E8.{12,32}(?<channel>$rxChannel).{300,500}68-(?<flag>`$1-.{6}`$2)"
                forEach ($variant in $variants) {
                    $pattern = $flagOffsStr -replace '^(..)-.{6}(..)', $variant
                    "`tLooking for $($pattern -replace '\?<.+?>', '')..."
                    $minDiff = 65536
                    foreach ($m in [regex]::matches($code, $pattern)) {
                        $maybeFlagOffs = $BC::toUInt32($bytes, $m.groups['flag'].index/3)
                        $diff = [Math]::abs($maybeFlagOffs - $flagOffs)
                        if ($diff % 256 -eq 0 -and $diff -lt $minDiff) {
                            $minDiff = $diff
                            $chanpos = $m.groups['channel'].index/3 + 2
                        }
                    }
                }
                if (!$chanpos) { throw }
            }
        } catch {
            write-host -f red "`tUnable to find the channel code, try updating me"
            write-host -f red "`thttp://stackoverflow.com/a/30361260"
            return
        }
        $bytes[$chanpos] = 9
        "`tPATCHED Chrome release channel restriction"
    
        "`tWriting to a temporary dll..."
        [IO.File]::WriteAllBytes("$dll.new",$bytes)
    
        "`tBacking up the original dll..."
        move -literal $dll "$dll.bak" -force
    
        "`tRenaming the temporary dll as the original dll..."
        move -literal "$dll.new" $dll -force
    
        $pathsDone[$path.toLower()] = $true
        write-host -f green "`tDONE.`n"
        [GC]::Collect()
    }
    
    main
    Ответ написан
    24 комментария
  • Что нужно освоить веб разработчику чтобы облегчить себе жизнь?

    evnuh
    @evnuh
    Поиск Гугл помог мне, впусти и ты его в свой дом
    1) Выбрать и настроить IDE. Освоиться в ней.
    2) Научиться работать с системами контроля версий.
    3) Научиться учиться. Выучить английский, научиться пользоваться гуглом.
    4) Научиться писать код.
    5) Научиться дебажить свой код.
    6) Научиться тестированию кода.
    7) Понять, как работает компьютер, сетевой стек, браузер, как устроены базы данных, как работает компиляция. Освоить DevOps.
    8) После 7 пункта уже можно учиться оптимизировать свой код.
    9) Научиться решать задачи, а не тупо писать код. Разобраться, когда и где и как использовать разные технологии,
    10) Научиться работать с людьми. Научиться продавать себя и свой продукт.
    11) Выкинуть хлам из дома.
    12) Старых позвать друзей.
    Ответ написан
    1 комментарий
  • Что нужно освоить веб разработчику чтобы облегчить себе жизнь?

    tot0ro
    @tot0ro
    Front - end developer
    1. IDE
    2. xdebug
    3. git
    4. composer
    5.bower
    6.npm/bower
    6. less/stulys/sass
    7. grunt/gulp/webpack
    8. apache/nginx
    9. apc/opcache/memcache/varnish etc
    10. bootstrap
    11. VIM!!!!!!!!!
    12. English!!!!!!!!!!
    13. Все дырки через границу
    14. Умение не читать ИТ литературу русских программистов за исключением Макарова, Индутного
    15. Ненавидеть Попова
    Ответ написан
    40 комментариев
  • Деградация производительности PostgreSQL 9.1 -> 9.5?

    Сколько новых фич было добавлено в 9.5? Например без upsert я уже не представляю как жил раньше, без ранее добаленного jsonb формата и прочее.
    Вы хотите новые фичи в приложении без деградации производительности? :)
    Ответ написан
    4 комментария
  • Зачем нужен Gulp?

    @artinnok
    бекенд-программист
    CSS и JS:
    К примеру, у вас имеется большое количество (Х штук) css или js файлов, которое вы подключаете на своих страницах посредством тэгов <link> и <src>.
    При загрузке страницы, браузер клиента будет отправлять X запросов к вашему серверу, а ваш сервер должен будет ответить на X запросов.
    Это:
    1. Тормозит загрузку страницы - будете ждать ответа от сервера
    2. Загружает ваш сервер

    С помощью сборщиков фронтэнда вы можете "склеить" все файлы в один - main.css и main.js, которые будут отдаваться 2 запросами с сервера. Также, вы сможете минифицировать CSS и JS. Под минификацией подразумевается уменьшение размеров файла на диске. Естественно, более легкий файлы будет быстрее прогружаться + минимальное количество запросов к серверу.

    IMG:
    К примеру, у вас имеется Х изображений размером 700 Кбайт. Клиенту надо будет загрузить 700 * X Кбайт. Если вы пропустите свои изображения через Gulp, то вы получите изображения с меньшим размером на диске и такого же качества, т.е. клиенту придется прогрузить примерно (500-600) * X Кбайт.
    Ответ написан
    1 комментарий
  • Бесплатный проект для портфолио превратился в бесконечный. Как быть?

    POS_troi
    @POS_troi
    СадоМазо Админ, флудер, троль.
    Вариант 1 - послать и забыть.
    Вариант 2 - переводить из бесплатного в платный.

    Базовый функционал есть? Есть
    Клиент уже доволен? Доволен
    Пора платить деньгу, а так он почувствовал халяву и не слезет с вас.
    Ответ написан
    6 комментариев